[Git][ghc/ghc][wip/mangoiv/directory-bump] libraries/directory: bump submodule to v1.3.11.0
by Magnus (@MangoIV) 28 May '26
by Magnus (@MangoIV) 28 May '26
28 May '26
Magnus pushed to branch wip/mangoiv/directory-bump at Glasgow Haskell Compiler / GHC
Commits:
95252514 by mangoiv at 2026-05-28T15:22:54+02:00
libraries/directory: bump submodule to v1.3.11.0
Fixes #27312
- - - - -
2 changed files:
- + changelog.d/27312
- libraries/directory
Changes:
=====================================
changelog.d/27312
=====================================
@@ -0,0 +1,7 @@
+section: packaging
+issues: #27312
+mrs: !16114
+synopsis:
+ bump directory submodule to v1.3.11.0
+description:
+ This submodule bump relaces some version constraints for directory.
=====================================
libraries/directory
=====================================
@@ -1 +1 @@
-Subproject commit 82d5cfb2c597fa0bb67175c47b682dee1d24ee7a
+Subproject commit 12d17af8ee2f84fc6b6ac0d4e1734952789ddd3e
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/95252514062caacf040cda5e1ca4de7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/95252514062caacf040cda5e1ca4de7…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
28 May '26
Magnus pushed new branch wip/mangoiv/directory-bump at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/mangoiv/directory-bump
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/davide/ghc-internal-def] Hadrian: create a ghc-internal .def file per ghc-internal dll
by David Eichmann (@DavidEichmann) 28 May '26
by David Eichmann (@DavidEichmann) 28 May '26
28 May '26
David Eichmann pushed to branch wip/davide/ghc-internal-def at Glasgow Haskell Compiler / GHC
Commits:
d687ebbf by David Eichmann at 2026-05-28T14:14:26+01:00
Hadrian: create a ghc-internal .def file per ghc-internal dll
The .def file generated from rts/win32/libHSghc-internal.def.in contains
the name of the ghc-internal dll. The correct dll name differs based
on if the dll is inplace/final and if using the Dynamic way. Previously,
this was not accounted for and inconsistent dlls names where used. That
led to failure when loading dlls at runtime in experiments with windows
dynamic linking.
- - - - -
4 changed files:
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Rts.hs
- rts/win32/libHSghc-internal.def.in
Changes:
=====================================
hadrian/src/Rules/Generate.hs
=====================================
@@ -377,7 +377,6 @@ templateRules = do
, interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1
, interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2
]
- templateRule "rts/win32/libHSghc-internal.def" projectVersion
templateRule "docs/index.html" $ packageUnitIds Stage1
templateRule "docs/users_guide/ghc_config.py" $ mconcat
[ projectVersion
=====================================
hadrian/src/Rules/Library.hs
=====================================
@@ -9,6 +9,7 @@ import GHC.Toolchain.Target (Target(tgtArchOs))
import Base
import Context
+import qualified Data.List as List
import Expression hiding (way, package, stage)
import Oracles.ModuleFiles
import Packages
@@ -20,6 +21,7 @@ import Utilities
import Data.Time.Clock
import Rules.Generate (generatedDependencies)
import Oracles.Flag
+import Way.Type (wayToUnits)
-- * Library 'Rules'
@@ -203,13 +205,29 @@ extraObjects context
| package context == rts = do
target <- interpretInContext context getStagedTarget
- builddir <- buildPath context
- return [ builddir -/- "libHSghc-internal.dll.a"
- | archOS_OS (tgtArchOs target) == OSMinGW32
- , Dynamic `wayUnit` way context ]
+ if not (archOS_OS (tgtArchOs target) == OSMinGW32
+ && Dynamic `wayUnit` way context)
+ then return []
+ else do
+ -- Find the ghc-internal library file name
+ ghcInternalDllName <- takeFileName <$> pkgLibraryFile Context {
+ stage = stage context,
+ way = rtsWayToLibraryWay (way context),
+ iplace = iplace context,
+ package = ghcInternal
+ }
+
+ builddir <- buildPath context
+ return [ builddir -/- ghcInternalDllName <> ".a"]
| otherwise = return []
+-- | The rts is compiled in many different ways, but libraries are only built in
+-- (non)Dynamic and (non)Profiled ways. This function converts the rts way into
+-- compatible library way.
+rtsWayToLibraryWay :: Way -> Way
+rtsWayToLibraryWay = wayFromUnits . List.intersect [Dynamic, Profiling] . wayToUnits
+
-- | Return all the object files to be put into the library we're building for
-- the given 'Context'.
libraryObjects :: Context -> Action [FilePath]
=====================================
hadrian/src/Rules/Rts.hs
=====================================
@@ -13,11 +13,19 @@ rtsRules = priority 3 $ do
-- to be linked into the rts dll.
forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do
let buildPath = root -/- buildDir (rtsContext stage)
- buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib
+ buildPath -/- "libHSghc-internal-*.def" %> buildGhcInternalImportDef
+ buildPath -/- "libHSghc-internal-*.dll.a" %> buildGhcInternalImportLib
+
+buildGhcInternalImportDef :: FilePath -> Action ()
+buildGhcInternalImportDef target = do
+ templateIn <- readFile' "rts/win32/libHSghc-internal.def.in"
+ let dllName = takeFileName target -<.> "dll"
+ templateOut = replace "@GhcInternalDll@" dllName templateIn
+ writeFile' target templateOut
buildGhcInternalImportLib :: FilePath -> Action ()
buildGhcInternalImportLib target = do
- let input = "rts/win32/libHSghc-internal.def"
+ let input = dropExtensions target <.> "def" -- the .def file
output = target -- the .dll.a import lib
need [input]
runBuilder Dlltool ["-d", input, "-l", output] [input] [output]
=====================================
rts/win32/libHSghc-internal.def.in
=====================================
@@ -1,4 +1,4 @@
-LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll
+LIBRARY @GhcInternalDll@
EXPORTS
init_ghc_hs_iface
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d687ebbf20c5b4b0ed4401d26bc6096…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d687ebbf20c5b4b0ed4401d26bc6096…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/spj-reinstallable-base2] 2 commits: Add composition library as test for 27013
by Rodrigo Mesquita (@alt-romes) 28 May '26
by Rodrigo Mesquita (@alt-romes) 28 May '26
28 May '26
Rodrigo Mesquita pushed to branch wip/spj-reinstallable-base2 at Glasgow Haskell Compiler / GHC
Commits:
496c99bb by Rodrigo Mesquita at 2026-05-26T13:52:33+01:00
Add composition library as test for 27013
- - - - -
48c0a754 by Rodrigo Mesquita at 2026-05-28T13:52:40+01:00
Add recompilation avoidance fails test for GHC.Essentials package changed
- - - - -
10 changed files:
- compiler/GHC/Driver/Pipeline/Execute.hs
- + testsuite/tests/cabal/T27013a/Makefile
- + testsuite/tests/cabal/T27013a/Setup.hs
- + testsuite/tests/cabal/T27013a/all.T
- + testsuite/tests/cabal/T27013a/composition.cabal
- + testsuite/tests/cabal/T27013a/src/Data/Composition.hs
- + testsuite/tests/driver/T27013b/Makefile
- + testsuite/tests/driver/T27013b/T27013b.stdout
- + testsuite/tests/driver/T27013b/X.hs
- + testsuite/tests/driver/T27013b/all.T
Changes:
=====================================
compiler/GHC/Driver/Pipeline/Execute.hs
=====================================
@@ -670,7 +670,6 @@ runHscPhase pipe_env hsc_env0 input_fn src_flavour = do
-- gather the imports and module name
(hspp_buf,mod_name,imps,src_imps) <- do
buf <- hGetStringBuffer input_fn
- -- TODO: handle implicit knownkey names here?
let rn_pkg_qual = renameRawPkgQual (hsc_unit_env hsc_env)
rn_imps = fmap (\(s, rpk, lmn@(L _ mn)) -> (s, rn_pkg_qual mn rpk, lmn))
sec = initSourceErrorContext dflags
=====================================
testsuite/tests/cabal/T27013a/Makefile
=====================================
@@ -0,0 +1,22 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+SETUP=./Setup -v0
+
+# Reproducer for #27013 (!15899#note_676801).
+#
+# The `composition` package depends on neither `base` nor `ghc-internal`
+# (see composition.cabal: no build-depends). It uses NoImplicitPrelude
+# and defines its own `(.)`. Building it should not require GHC to load
+# known-key modules from `base` such as `GHC.Essentials`.
+
+T27013a: clean
+ '$(GHC_PKG)' init tmp.d
+ '$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make Setup
+ $(SETUP) clean
+ $(SETUP) configure $(CABAL_MINIMAL_BUILD) --with-ghc='$(TEST_HC)' --with-hc-pkg='$(GHC_PKG)' --ghc-options='$(TEST_HC_OPTS)' --package-db=tmp.d
+ $(SETUP) build
+
+clean :
+ $(RM) -r tmp.d dist Setup$(exeext) *.o *.hi
=====================================
testsuite/tests/cabal/T27013a/Setup.hs
=====================================
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
=====================================
testsuite/tests/cabal/T27013a/all.T
=====================================
@@ -0,0 +1,4 @@
+test('T27013a',
+ [extra_files(['src/', 'composition.cabal', 'Setup.hs'])],
+ makefile_test,
+ [])
=====================================
testsuite/tests/cabal/T27013a/composition.cabal
=====================================
@@ -0,0 +1,24 @@
+name: composition
+version: 1.0.2.2
+synopsis: Combinators for unorthodox function composition
+
+license: BSD3
+license-file: LICENSE
+author: Dan Burton
+maintainer: danburton.email(a)gmail.com
+bug-reports:
+ https://github.com/DanBurton/composition/issues
+
+category: Data
+build-type: Simple
+cabal-version: >=1.10
+
+library
+ default-language: Haskell2010
+ hs-source-dirs: src
+ exposed-modules: Data.Composition
+ default-extensions: NoImplicitPrelude
+
+source-repository head
+ type: git
+ location: git://github.com/DanBurton/composition.git
=====================================
testsuite/tests/cabal/T27013a/src/Data/Composition.hs
=====================================
@@ -0,0 +1,149 @@
+-- | This module is for convenience and demonstrative purposes
+-- more than it is for providing actual value.
+-- I do not recommend that you rely on this module
+-- for performance-sensitive code.
+-- Because this module is not based on Prelude's (.),
+-- some chances at optimization might be missed by your compiler.
+module Data.Composition (
+ -- * Math
+ (∘)
+
+ -- * Colons and dots
+ , (.:)
+ , (.:.)
+ , (.::)
+ , (.::.)
+ , (.:::)
+ , (.:::.)
+ , (.::::)
+ , (.::::.)
+
+ -- * Asterisks
+ , (.*)
+ , (.**)
+ , (.***)
+ , (.****)
+ , (.*****)
+ , (.******)
+ , (.*******)
+ , (.********)
+
+ -- * composeN
+ , compose1
+ , compose2
+ , compose3
+ , compose4
+ , compose5
+ , compose6
+ , compose7
+ , compose8
+ , compose9
+
+ ) where
+
+-- Not exported. This is defined here to remove the dependency on base
+(.) :: (b -> c) -> (a -> b) -> a -> c
+(f . g) x = f (g x)
+
+infixr 9 .
+
+-- | The mathematical symbol for function composition.
+(∘) :: (b -> c) -> (a -> b) -> a -> c
+(∘) = (.)
+
+infixr 9 ∘
+
+-- | Compose two functions. @f .: g@ is similar to @f . g@
+-- except that @g@ will be fed /two/ arguments instead of one
+-- before handing its result to @f@.
+--
+-- This function is defined as
+--
+-- > (f .: g) x y = f (g x y)
+--
+-- Example usage:
+--
+-- > concatMap :: (a -> [b]) -> [a] -> [b]
+-- > concatMap = concat .: map
+--
+-- Notice how /two/ arguments
+-- (the function /and/ the list)
+-- will be given to @map@ before the result
+-- is passed to @concat@. This is equivalent to:
+--
+-- > concatMap f xs = concat (map f xs)
+(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
+(f .: g) x y = f (g x y)
+
+infixr 8 .:
+
+-- | Equivalent to '.:'
+--
+-- The pattern of appending asterisks is
+-- straightforward to extend to similar functions:
+-- (compose2 = .*, compose3 = .**, etc).
+-- However, @.:@ has been commonly adopted amongst Haskellers,
+-- and the need for compose3 and beyond is rare in practice.
+(.*) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
+(.*) = (.) . (.)
+
+infixr 8 .*
+
+(.**) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
+(.**) = (.) . (.*)
+
+(.***) = (.) . (.**)
+(.****) = (.) . (.***)
+(.*****) = (.) . (.****)
+(.******) = (.) . (.*****)
+(.*******) = (.) . (.******)
+(.********) = (.) . (.*******)
+
+infixr 8 .**
+infixr 8 .***
+infixr 8 .****
+infixr 8 .*****
+infixr 8 .******
+infixr 8 .*******
+infixr 8 .********
+
+
+-- | @composeN f g@ means give @g@ @N@ inputs
+-- and then pass its result to @f@.
+compose1 :: (b -> c) -> (a -> b) -> a -> c
+compose1 = (.)
+
+compose2 :: (c -> d) -> (a -> b -> c) -> a -> b -> d
+compose2 = (.*)
+
+compose3 :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
+compose3 = (.**)
+
+compose4 = (.***)
+compose5 = (.****)
+compose6 = (.*****)
+compose7 = (.******)
+compose8 = (.*******)
+compose9 = (.********)
+
+-- | One compact pattern for composition operators is to
+-- "count the dots after the first one",
+-- which begins with the common '.:', and proceeds by first
+-- appending another @.@ and then replacing it with @:@
+(.:.) :: (d -> e) -> (a -> b -> c -> d) -> a -> b -> c -> e
+(.:.) = (.**)
+
+(.::) = (.***)
+(.::.) = (.****)
+(.:::) = (.*****)
+(.:::.) = (.******)
+(.::::) = (.*******)
+(.::::.) = (.********)
+
+infixr 8 .:.
+infixr 8 .::
+infixr 8 .::.
+infixr 8 .:::
+infixr 8 .:::.
+infixr 8 .::::
+infixr 8 .::::.
=====================================
testsuite/tests/driver/T27013b/Makefile
=====================================
@@ -0,0 +1,14 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+# Test that compiling X.hs without implicit Prelude does not recompile X the
+# second time or third time. In !15899, X.hs was recompiled because of an
+# incorrect "GHC.Essentials package changed"
+clean:
+ rm -f *.o *.hi
+
+T27013b: clean
+ '$(TEST_HC)' $(TEST_HC_OPTS) --make X.hs
+ '$(TEST_HC)' $(TEST_HC_OPTS) --make X.hs
+ '$(TEST_HC)' $(TEST_HC_OPTS) --make X.hs
=====================================
testsuite/tests/driver/T27013b/T27013b.stdout
=====================================
@@ -0,0 +1 @@
+[1 of 1] Compiling X ( X.hs, X.o )
=====================================
testsuite/tests/driver/T27013b/X.hs
=====================================
@@ -0,0 +1,3 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module X where
+x = 3
=====================================
testsuite/tests/driver/T27013b/all.T
=====================================
@@ -0,0 +1,2 @@
+test('T27013b', [extra_files(['X.hs'])],
+ makefile_test, [])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/989b38cbe9dbf29b8673f3d4b27005…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/989b38cbe9dbf29b8673f3d4b27005…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/davide/ghc-internal-def] Hadrian: create a ghc-internal .def file per ghc-internal dll
by David Eichmann (@DavidEichmann) 28 May '26
by David Eichmann (@DavidEichmann) 28 May '26
28 May '26
David Eichmann pushed to branch wip/davide/ghc-internal-def at Glasgow Haskell Compiler / GHC
Commits:
9c2789b7 by David Eichmann at 2026-05-28T14:05:02+01:00
Hadrian: create a ghc-internal .def file per ghc-internal dll
The .def file generated from rts/win32/libHSghc-internal.def.in contains
the name of the ghc-internal dll. The correct dll name differs based
on if the dll is inplace/final and if using the Dynamic way. Previously,
this was not accounted for and inconsistent dlls names where used. That
led to failure when loading dlls at runtime in experiments with windows
dynamic linking.
- - - - -
4 changed files:
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Rts.hs
- rts/win32/libHSghc-internal.def.in
Changes:
=====================================
hadrian/src/Rules/Generate.hs
=====================================
@@ -377,7 +377,6 @@ templateRules = do
, interpolateSetting "ProjectPatchLevel1" ProjectPatchLevel1
, interpolateSetting "ProjectPatchLevel2" ProjectPatchLevel2
]
- templateRule "rts/win32/libHSghc-internal.def" projectVersion
templateRule "docs/index.html" $ packageUnitIds Stage1
templateRule "docs/users_guide/ghc_config.py" $ mconcat
[ projectVersion
=====================================
hadrian/src/Rules/Library.hs
=====================================
@@ -9,6 +9,7 @@ import GHC.Toolchain.Target (Target(tgtArchOs))
import Base
import Context
+import qualified Data.List as List
import Expression hiding (way, package, stage)
import Oracles.ModuleFiles
import Packages
@@ -20,6 +21,7 @@ import Utilities
import Data.Time.Clock
import Rules.Generate (generatedDependencies)
import Oracles.Flag
+import Way.Type (wayToUnits)
-- * Library 'Rules'
@@ -203,13 +205,29 @@ extraObjects context
| package context == rts = do
target <- interpretInContext context getStagedTarget
- builddir <- buildPath context
- return [ builddir -/- "libHSghc-internal.dll.a"
- | archOS_OS (tgtArchOs target) == OSMinGW32
- , Dynamic `wayUnit` way context ]
+ if not (archOS_OS (tgtArchOs target) == OSMinGW32
+ && Dynamic `wayUnit` way context)
+ then return []
+ else do
+ -- Find the ghc-internal library file name
+ ghcInternalDllName <- takeFileName <$> pkgLibraryFile Context {
+ stage = stage context,
+ way = rtsWayToLibraryWay (way context),
+ iplace = iplace context,
+ package = ghcInternal
+ }
+
+ builddir <- buildPath context
+ return [ builddir -/- ghcInternalDllName <> ".a"]
| otherwise = return []
+-- | The rts is compiled in many different ways, but libraries are only built in
+-- (non)Dynamic and (non)Profiled ways. This function converts the rts way into
+-- compatible library way.
+rtsWayToLibraryWay :: Way -> Way
+rtsWayToLibraryWay = wayFromUnits . List.intersect [Dynamic, Profiling] . wayToUnits
+
-- | Return all the object files to be put into the library we're building for
-- the given 'Context'.
libraryObjects :: Context -> Action [FilePath]
=====================================
hadrian/src/Rules/Rts.hs
=====================================
@@ -13,11 +13,19 @@ rtsRules = priority 3 $ do
-- to be linked into the rts dll.
forM_ [Stage1, Stage2, Stage3 ] $ \ stage -> do
let buildPath = root -/- buildDir (rtsContext stage)
- buildPath -/- "libHSghc-internal.dll.a" %> buildGhcInternalImportLib
+ buildPath -/- "libHSghc-internal-*.def" %> buildGhcInternalImportDef
+ buildPath -/- "libHSghc-internal-*.dll.a" %> buildGhcInternalImportLib
+
+buildGhcInternalImportDef :: FilePath -> Action ()
+buildGhcInternalImportDef target = do
+ templateIn <- readFile' "rts/win32/libHSghc-internal.def.in"
+ let dllName = (dropExtension (takeFileName target)) <.> "dll"
+ templateOut = replace "@GhcInternalDll@" dllName templateIn
+ writeFile' target templateOut
buildGhcInternalImportLib :: FilePath -> Action ()
buildGhcInternalImportLib target = do
- let input = "rts/win32/libHSghc-internal.def"
+ let input = dropExtensions target <.> "def" -- the .def file
output = target -- the .dll.a import lib
need [input]
runBuilder Dlltool ["-d", input, "-l", output] [input] [output]
=====================================
rts/win32/libHSghc-internal.def.in
=====================================
@@ -1,4 +1,4 @@
-LIBRARY libHSghc-internal-@ProjectVersionForLib@.0-ghc@ProjectVersion@.dll
+LIBRARY @GhcInternalDll@
EXPORTS
init_ghc_hs_iface
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9c2789b7f9645758e9f7ca670bbadf8…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9c2789b7f9645758e9f7ca670bbadf8…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/jeltsch/textual-bytecode-output] 2 commits: Work in progress
by Wolfgang Jeltsch (@jeltsch) 28 May '26
by Wolfgang Jeltsch (@jeltsch) 28 May '26
28 May '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/textual-bytecode-output at Glasgow Haskell Compiler / GHC
Commits:
913f5c1b by Wolfgang Jeltsch at 2026-05-28T15:51:27+03:00
Work in progress
- - - - -
c7150e2d by Wolfgang Jeltsch at 2026-05-28T15:51:41+03:00
`CompiledByteCode` wibbles
- - - - -
5 changed files:
- compiler/GHC/ByteCode/Serialize.hs
- + compiler/GHC/ByteCode/Show.hs
- compiler/ghc.cabal.in
- ghc/GHC/Driver/Session/Mode.hs
- ghc/Main.hs
Changes:
=====================================
compiler/GHC/ByteCode/Serialize.hs
=====================================
@@ -6,7 +6,7 @@
{- | This module implements the serialization of bytecode objects to and from disk.
-}
module GHC.ByteCode.Serialize
- ( writeBinByteCode, readBinByteCode
+ ( writeBinByteCode, readBinByteCode, readOnDiskModuleByteCode
, ModuleByteCode(..)
, BytecodeLibX(..)
, BytecodeLib
=====================================
compiler/GHC/ByteCode/Show.hs
=====================================
@@ -0,0 +1,139 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+
+-- | […]
+module GHC.ByteCode.Show (showByteCode) where
+
+import Data.Ord ((<))
+import Data.Function (($), (&), (.))
+import Data.Bool (otherwise)
+import Data.Int (Int)
+import Data.Word (Word8)
+import Data.Maybe (maybe)
+import Data.List (map, zipWith)
+import Data.String (String)
+import Data.ByteString (ByteString, null, length, unpack)
+import Numeric (showHex)
+import System.IO (IO, FilePath)
+import GHC.Types.SrcLoc (noSrcSpan)
+import GHC.Types.Error (MessageClass (MCDump))
+import GHC.Utils.Logger (Logger, logMsg)
+import GHC.Utils.Outputable
+ (
+ defaultDumpStyle,
+ SDoc,
+ text,
+ (<+>),
+ hsep,
+ nest,
+ vcat,
+ withPprStyle,
+ ppr
+ )
+import GHC.ByteCode.Types (CompiledByteCode (..))
+import GHC.ByteCode.Binary (OnDiskModuleByteCode (..))
+import GHC.ByteCode.Serialize (readOnDiskModuleByteCode)
+import GHC.Driver.Env.Types (HscEnv)
+
+-- | […]
+showByteCode :: Logger -> HscEnv -> FilePath -> IO ()
+showByteCode logger env path = do
+ byteCode <- readOnDiskModuleByteCode env path
+ logMsg logger
+ MCDump
+ noSrcSpan
+ (withPprStyle defaultDumpStyle $ pprOnDiskModuleByteCode byteCode)
+
+-- | […]
+pprOnDiskModuleByteCode :: OnDiskModuleByteCode -> SDoc
+pprOnDiskModuleByteCode OnDiskModuleByteCode {..}
+ = vcat $
+ [
+ text "module" <+> ppr odgbc_module,
+ nest 2 $ vcat
+ [
+ text "hash:"
+ <+> ppr odgbc_hash,
+ text "compiled bytecode:"
+ <+> pprCompiledByteCode odgbc_compiled_byte_code,
+ text "contents of object files:"
+ <+> pprObjectFileContents odgbc_foreign
+ ]
+ ]
+
+-- | […]
+pprCompiledByteCode :: CompiledByteCode -> SDoc
+pprCompiledByteCode CompiledByteCode {..}
+ = vcat
+ [
+ text "bytecode objects"
+ <+> pprByteCodeObjects bc_bcos,
+ text "data constructor info tables:"
+ <+> pprDataConstructorInfoTables bc_itbls,
+ text "top-level strings:"
+ <+> pprTopLevelStrings bc_strs,
+ text "break points:"
+ <+> maybe (text "<none>") pprInternalBreakPoints bc_breaks,
+ text "static-pointer table entries:"
+ <+> pprStaticPointerTableEntries bc_spt_entries,
+ text "HPC information:"
+ <+> pprHPCInfo bc_hpc_info
+ ]
+
+-- | […]
+pprByteCodeObjects :: a -> SDoc
+pprByteCodeObjects = pprByteCodeObjects
+
+-- | […]
+pprDataConstructorInfoTables :: a -> SDoc
+pprDataConstructorInfoTables = pprDataConstructorInfoTables
+
+-- | […]
+pprTopLevelStrings :: a -> SDoc
+pprTopLevelStrings = pprTopLevelStrings
+
+-- | […]
+pprInternalBreakPoints :: a -> SDoc
+pprInternalBreakPoints = pprInternalBreakPoints
+
+-- | […]
+pprStaticPointerTableEntries :: a -> SDoc
+pprStaticPointerTableEntries = pprStaticPointerTableEntries
+
+-- | […]
+pprHPCInfo :: a -> SDoc
+pprHPCInfo = pprHPCInfo
+
+-- | […]
+pprObjectFileContents :: [ByteString] -> SDoc
+pprObjectFileContents = vcatOrNone . zipWith pprEntry [0 ..] where
+
+ pprEntry :: Int -> ByteString -> SDoc
+ pprEntry ix content
+ = vcat [
+ hsep [
+ text "file",
+ ppr ix,
+ text "of length",
+ ppr (length content)
+ ],
+ nest 2 $ pprByteString content
+ ]
+
+-- | […]
+pprByteString :: ByteString -> SDoc
+pprByteString byteString
+ | null byteString = text "<empty>"
+ | otherwise = byteString & unpack & map pprByte & hsep
+
+-- | […]
+pprByte :: Word8 -> SDoc
+pprByte byte = text $ if byte < 16 then '0' : unpadded else unpadded where
+
+ unpadded :: String
+ unpadded = showHex byte ""
+
+-- | […]
+vcatOrNone :: [SDoc] -> SDoc
+vcatOrNone [] = text "<none>"
+vcatOrNone docs = vcat docs
=====================================
compiler/ghc.cabal.in
=====================================
@@ -217,6 +217,7 @@ Library
GHC.ByteCode.Linker
GHC.ByteCode.Recomp.Binary
GHC.ByteCode.Serialize
+ GHC.ByteCode.Show
GHC.ByteCode.Types
GHC.Cmm
GHC.Cmm.BlockId
=====================================
ghc/GHC/Driver/Session/Mode.hs
=====================================
@@ -77,6 +77,7 @@ isShowGhciUsageMode _ = False
data PostLoadMode
= ShowInterface FilePath -- ghc --show-iface
+ | ShowByteCode FilePath -- ghc --show-byte-code
| DoMkDependHS -- ghc -M
| StopBefore StopPhase -- ghc -E | -C | -S
-- StopBefore StopLn is the default
@@ -101,6 +102,9 @@ showUnitsMode = mkPostLoadMode ShowPackages
showInterfaceMode :: FilePath -> Mode
showInterfaceMode fp = mkPostLoadMode (ShowInterface fp)
+showByteCodeMode :: FilePath -> Mode
+showByteCodeMode fp = mkPostLoadMode (ShowByteCode fp)
+
stopBeforeMode :: StopPhase -> Mode
stopBeforeMode phase = mkPostLoadMode (StopBefore phase)
@@ -231,9 +235,11 @@ mode_flags =
replaceSpace ' ' = '-'
replaceSpace c = c
] ++
- ------- interfaces ----------------------------------------------------
- [ defFlag "-show-iface" (HasArg (\f -> setMode (showInterfaceMode f)
+ ------- textual output of generated data -----------------------------
+ [ defFlag "-show-iface" (HasArg (\f -> setMode (showInterfaceMode f)
"--show-iface"))
+ , defFlag "-show-byte-code" (HasArg (\f -> setMode (showByteCodeMode f)
+ "--show-byte-code"))
------- primary modes ------------------------------------------------
, defFlag "c" (PassFlag (\f -> do setMode (stopBeforeMode NoStop) f
=====================================
ghc/Main.hs
=====================================
@@ -73,6 +73,8 @@ import GHC.SysTools.BaseDir
import GHC.Iface.Load
import GHC.Iface.Recomp.Binary ( fingerprintBinMem )
+import GHC.ByteCode.Show ( showByteCode )
+
import GHC.Tc.Utils.Monad ( initIfaceCheck )
import GHC.Iface.Errors.Ppr
@@ -266,6 +268,7 @@ main' postLoadMode units dflags0 args flagWarnings = do
(hsc_units hsc_env)
(hsc_NC hsc_env)
f
+ ShowByteCode f -> liftIO $ showByteCode logger hsc_env f
DoMake -> doMake units srcs
DoMkDependHS -> doMkDependHS (map fst srcs)
StopBefore p -> liftIO (oneShot hsc_env p srcs)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6ad9b2334ffd78b41e06ae8182ae43…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6ad9b2334ffd78b41e06ae8182ae43…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/jeltsch/textual-bytecode-output
by Wolfgang Jeltsch (@jeltsch) 28 May '26
by Wolfgang Jeltsch (@jeltsch) 28 May '26
28 May '26
Wolfgang Jeltsch pushed new branch wip/jeltsch/textual-bytecode-output at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/jeltsch/textual-bytecode-outp…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T27103-nub] 36 commits: AArch64: use ASR not LSR for MO_U_Shr at W8/W16
by Simon Jakobi (@sjakobi2) 28 May '26
by Simon Jakobi (@sjakobi2) 28 May '26
28 May '26
Simon Jakobi pushed to branch wip/sjakobi/T27103-nub at Glasgow Haskell Compiler / GHC
Commits:
50188615 by Ian Duncan at 2026-05-14T13:45:07+02:00
AArch64: use ASR not LSR for MO_U_Shr at W8/W16
The unsigned right shift (MO_U_Shr) for sub-word widths (W8, W16)
with a variable shift amount was emitting ASR (arithmetic/signed shift
right) after zero-extending with UXTB/UXTH. This should be LSR
(logical/unsigned shift right). After zero-extension the upper bits
happen to be 0 so ASR produces the same result, but it is semantically
wrong and would break if the zero-extension were ever optimized away.
Includes assembly output test (grep for lsr) and runtime test
verifying unsigned right shift of Word8 and Word16 values.
- - - - -
28666fbf by Vladislav Zavialov at 2026-05-19T12:44:05-04:00
Add type families: Tuple, Constraints, Tuple#, Sum# (#27179)
These type families map tuples of types to the corresponding Tuple<N>,
Tuple<N>#, CTuple<N>, and Sum<N># types. Some examples at N=2:
Tuple (Int, Bool) = Tuple2 Int Bool
Constraints (Show a, Eq a) = CTuple2 (Show a) (Eq a)
Tuple# (Int#, Float#) = Tuple2# Int# Float#
Sum# (Int#, Float#) = Sum2# Int# Float#
See GHC Proposal #145 "Non-punning list and tuple syntax".
To make the Sum# instance at N=64 possible, this patch also introduces
the Sum64# constructor declaration and bumps mAX_SUM_SIZE from 63 to 64.
Metric Increase:
ghc_experimental_dir
- - - - -
41c2448b by Wen Kokke at 2026-05-19T12:44:53-04:00
rts: Add IPE event class for -l
This commit adds a new IPE event class to the -l RTS flag.
Previously, IPE events were enabled unconditionally.
However, the IPE events can easily grow to hundreds or thousands of megabytes.
With the new event class you can pass, e.g., -l-I to disable IPE events.
- - - - -
62536551 by Wen Kokke at 2026-05-19T12:44:53-04:00
ghc-internal: Add TraceFlags.traceIPE
- - - - -
e45312d1 by Wen Kokke at 2026-05-19T12:44:53-04:00
testsuite: Add test for TraceFlags.traceIpe
- - - - -
4768d9aa by Wen Kokke at 2026-05-19T12:44:53-04:00
ghc-internal: Add DebugFlags.ipe
- - - - -
bc1b5c69 by Wen Kokke at 2026-05-19T12:44:53-04:00
testsuite: Add test for DebugFlags.ipe
- - - - -
0da1543f by Duncan Coutts at 2026-05-19T12:45:37-04:00
Document removal of the signal-based interval timer
Update mentions within the RTS section of the users guide.
Add a changelog entry.
- - - - -
b2911514 by Duncan Coutts at 2026-05-19T12:45:37-04:00
Fix section for an recent changelog entry
- - - - -
d6d76a7a by David Eichmann at 2026-05-19T12:46:19-04:00
ghc-toolchain: implement llvm program versioning logic
- - - - -
2dd36fa3 by Wolfgang Jeltsch at 2026-05-20T04:49:52-04:00
Turn `Trustworthy` into `Safe` in `base` where possible
- - - - -
f4399dd1 by Wolfgang Jeltsch at 2026-05-20T04:50:37-04:00
Make the current `base` buildable with GHC 10.0
- - - - -
1a7de232 by Duncan Coutts at 2026-05-20T12:26:25-04:00
Hadrian: remove legacy rts .so symlinks
For compatibility with the old makefile based build system, hadrian had
rules to generate symlinks from unversioned to versioned names for the
rts .so/.dynlib file, like libHSrts-ghcx.y.so -> libHSrts-1.0.3-ghcx.y.so
We no longer need these symlinks since the makefile build system has
been retired some time ago. The need for these symlinks is awkward on
windows where we cannot (in practice) create symlinks. So rather than
make them conditional (non-windows), just remove them entirely.
- - - - -
286f1adf by fendor at 2026-05-20T12:27:09-04:00
Fix regression T27202: `:load` and `:add` work in GHCi
To fix the regression there are conceptually two major things that we
fix:
* We don't remove the `importDirs` from `interactive-session`
* When `:add`ing a module, we don't try to find them via PackageImports
* The PackageImport is wrong as we can't know the package-name at
this stage in ghc/UI.hs
What does it mean to not remove the `importDirs` from
`interactive-session`?
It means that, given some initial `DynFlags`, we will use those
`importDirs` in `interactive-session`.
The initial `DynFlags`, however, depend on how you initialise the GHC
session.
For a simple session, initialised by
ghc -isrc -this-unit-id main
It is simple, just use the `DynFlags` given on the cli.
Thus, `main` and `interactive-session` will have the same `DynFlags`,
except for the `homeUnitId` and `interactive-session` depends on `main`
by construction of the GHCi session.
What about a multiple home unit session, though?
ghc -unit @unit1 -unit @unit2
What are the `DynFlags` in this cli invocation? It shouldn't be either
`@unti1` nor `@unit2`, as the order shouldn't matter or any other
implicit condition.
For consistency, we decide that the initial `DynFlags` are the top
`DynFlags` on the cli, ignoring `-unit` flags.
Thus, in this example, there are no `importsDirs` regardless of what we
might find in `@unit1` and `@unit2`.
But in this invocation:
ghc -isrc -unit @unit1 -unit @unit2
The `interactive-session` will have the `importsDirs` `src`.
Note, `-isrc` will be inherited in `@unit1` and `@unit2`, so you need to
explicitly use `-i` to clear the `importsDirs`, in order to avoid
accidentally adding `src` as an import directory to all other home
units.
This fix has been made possible by the improvements introduced in
!15888, which avoids ambiguity when a home unit shares the `importsDirs`
with the `interactive-session`, on top of being much faster for multiple
home units.
Adds regression tests for T27202 for `:load`ing and `:add`ing modules
that are located in import directories.
- - - - -
728662de by fendor at 2026-05-20T12:27:09-04:00
Use home unit package db stacks in GHCi prompt and session unit
In order to import modules from home unit dependencies (e.g., `Data.Map`),
the ghci prompt unit needs to populate its `UnitState`.
This is tricky to handle correctly, which `PackageDBFlag`s should we use
to populate the `UnitState`?
We decide, the most intuitive solution for users is to depend on all
`PackageDBFlag`s, so that any dependency can be imported in GHCi.
This assumes consistency in the `PackageDBFlag`s, so no two home units
specify `PackageDBFlag`s that are inconsistent with each other.
We could simply concat all the `PackageDBFlag`s of the existing home
units, but later `PackageDBFlag`s shadow earlier ones, leading to the
last processed home units' `PackageDBFlag`s to shadow the earlier ones.
This is hard to fix, we need to give users the capability to provide ghc
options for the ghci prompt home unit.
However, as this is considerably more work, we decided on an
approximation that should work out most of the time.
Package Db stacks in cabal and stack follow a certain structure:
-no-user-package-db > -package-db $cabal-store > -package-db $local-db
The first two arguments are always the same, namely the
`-no-user-package-db` and `-package-db`.
We compute the longest common prefix over all home units, and use that
as the start of the package db stack. Then, over the rest of the
`PackageDBFlag`s, we simply take the union and append them to our
initial stack.
We assume, that the rest of package dbs only defines very few, "local"
units that are usually not shadowing each other.
This allows us to get a relatively consistent package database stack for
the ghci prompt home unit.
Similar reasoning applies to the session unit in order to add modules to
the session and have dependencies available in the module.
We do something similar for `-package` flags, to make sure only the
correct units are actually visible in the ghci session.
This time, we simply take the union of all `PackageFlag`s, allowing us
to import modules from the home unit dependencies.
In the future, it would be beneficial to allow the user to provide the
exact ghc options to control the visibilities. For now, this will have
to do.
- - - - -
740d89a0 by Simon Peyton Jones at 2026-05-20T17:20:44-04:00
Do not use mkCast during typechecking
This commit fixes #27219. The problem was that the typechecker was using
`mkCast`, whose assertion checks legitimately fail when applied to types
that contain unification variables.
- - - - -
a50fdb06 by Simon Peyton Jones at 2026-05-20T17:20:45-04:00
Major refactor of the Simplifier
The main payload of this patch is to refactor the Simplifer to avoid
repeated simplification when using Plan (AFTER) for rule rewrites.
The need for this was shown up by #26989.
See Note [Avoid repeated simplification] in GHC.Core.Opt.Simplify.Iteration.
Related refactoring:
* Refactor the two fields `sc_dup` and `sc_env` in `ApplyToVal` into one, `sc_env`.
Reason: the envt is irrelevant in the "simplified" case, so the data type describes
the possiblitiies much more accurately now.
* Some refactoring in `knownCon` to split off `wrapDataConFloats`.
* Refactor `lookupRule` and its auxiliary functions to return `RuleMatch`,
a new data type. See Note [data RuleMatch] in GHC.Core. Ditto for BuiltinRule.
This RuleMatch returns fragments of the target in rm_args and rm_floats,
leaving `rm_rhs` to be the stuff from the RULE itself.
Doing this has routine consequences in GHC.Core.Opt.ConstantFold. Many changes
there but all routine.
* When doing occurrence analysis on RULEs, make the occ-info on the rule
binders relate just to the RHS, not the LHS. See (OUR1) in
Note Note [OccInfo in unfoldings and rules]
This means that Lint must not complain about the fact that the patterns
in the RULE mentions binders that are marked dead.
See Note [Dead occurrences] in GHC.Core.Lint.
I changed the Core pretty-printer so that it didn't suppress dead binders,
else I can't see those binders in RULEs. That led to quite a lot of testsuite wibbles.
* Refactor FloatBinds, so that it is used both by
`exprIsConApp_mabye` and by `lookupRule`
* Move the definition of FloatBinds out of GHc.Core.Make, into GHC.Core.
* Add FloatTick as an extra constructor.
* Refactor `lookupRule` to use `FloatBinds` instead of `BindWrapper`.
This refactor just shares more code.
(Rename GHC.Core.Opt.FloatOut.FloatBinds to FloatLets, to avoid gratuitious
name clash with GHC.Core.FloatBinds.)
Corecion optimisation
* In simpleOpt, when composing coercions, call new function `optTransCo`.
This is much lighter weight than full blown coercion optimisation.
* Make `GHC.Core.Opt.Arity.pushCoValArg` and `pushCoTyArg` return the
coercionLKind of the coercion. This saves recomputing that coercionLKind
at the key call sites in GHC.Core.Opt.Simplify.Iteration.pushCast.
* Rename `addCoerce` in GHC.Core.Simplify.Iteration to become `pushCast`.
* In the `ApplyToVal` case of `pushCast` we had a very unsavoury call to `simplArg`.
I eliminated it by adding a field `sc_cast` to `ApplyToVal` that records any
pending casts. Much nicer now. See Note [The sc_cast field of ApplyToVal].
* Don't optimise coercions if the type-substitution is empty.
See Note [Optimising coercions] in GHC.Core.Opt.Simplify.Iteration.
The fix for #26838 is dramatic. For the test in perf/compiler/T26839 we have
Compiler allocs: Before: 7,363M
After: 688M
Compile time goes down generally. Here are compiler-alloc changes
over 0.5%:
CoOpt_Read(normal) 729,184,920 -0.7%
CoOpt_Singletons(normal) 666,916,960 -4.6% GOOD
LargeRecord(normal) 1,227,056,876 +1.1%
T12227(normal) 256,827,604 -4.6% GOOD
T12425(optasm) 76,879,410 -0.8%
T12545(normal) 787,826,918 -10.8% GOOD
T12707(normal) 775,186,464 -0.9%
T13253(normal) 318,599,596 -0.8%
T14766(normal) 685,857,320 -1.0%
T15304(normal) 1,123,333,422 -2.2%
T15630(normal) 123,142,330 -2.6%
T15630a(normal) 123,092,100 -2.6%
T15703(normal) 299,751,682 -2.9% GOOD
T17516(normal) 964,072,280 +1.0%
T18223(normal) 367,016,820 -6.2% GOOD
T18730(optasm) 130,643,770 -3.3% GOOD
T20261(normal) 535,608,584 -0.7%
T21839c(normal) 340,340,436 -0.9%
T24984(normal) 85,568,392 -1.9%
T3064(normal) 174,631,992 -1.2%
T3294(normal) 1,215,886,432 -0.7%
T5030(normal) 141,449,704 -17.2% GOOD
T5321Fun(normal) 258,484,744 -1.9%
T8095(normal) 770,532,232 -2.7%
T9630(normal) 858,423,408 -14.5% GOOD
T9872c(normal) 1,591,709,448 +0.7%
info_table_map_perf(normal) 19,700,614,458 -1.3%
geo. mean -0.7%
minimum -17.2%
maximum +1.1%
However, strangely there seems to be a 5.0% increase in CoOpt_Read in
the x86_64-linux-fedora43-validate+debug_info+ubsan job, although
there generally a /decrease/ in this test in other builds. The baseline
value looks strange. Anyway I'll just accept it.
Metric Decrease:
CoOpt_Singletons
T12227
T12545
T12707
T15703
T18223
T18730
T21839c
T5030
T9630
Metric Increase:
CoOpt_Read
- - - - -
834623d4 by Mrjtjmn at 2026-05-20T17:21:41-04:00
users-guide: Fix weird notation in "Summary of stolen syntax"
- - - - -
6f9d7c71 by Markus Läll at 2026-05-21T15:25:34-04:00
Use "grimily" instead of "grimly"
Fixes https://gitlab.haskell.org/ghc/ghc/-/issues/27221
- - - - -
50e999ca by fendor at 2026-05-21T15:26:18-04:00
Speed up 'closure' computation in `ghc-pkg`
Cache the set of already seen `UnitId`s and use `Set` operations to
speed up 'closure' computation.
Further simplify the implementation of 'closure' to account for the
actual usage.
As a consequence, we rename 'closure' to 'brokenPackages' to reflect its
purpose better after the simplification.
- - - - -
7ecc6184 by sheaf at 2026-05-21T15:27:10-04:00
TcMPluginHandling: be more lenient when no plugins
This change ensures that, if a function such as 'typecheckModule' was
invoked with 'NoTcMPlugins', GHC doesn't spuriously complain about TcM
plugins having already been stopped, as there were none to start with.
- - - - -
72c8de5c by Simon Jakobi at 2026-05-23T18:41:42-04:00
Implement List.elem via foldr
...in order to allow specialization to Eq instances.
The implementation of notElem is updated for consistency.`
Corresponding CLC proposal:
https://github.com/haskell/core-libraries-committee/issues/412
Addresses #27096.
- - - - -
3268c610 by Alan Zimmerman at 2026-05-23T18:42:30-04:00
EPA: Fix span for qualified multiline string
Fix the span for a qualified multiline string like
Text."""
I'm a multiline
Text value
!
"""
to extend to the end of the entire string, not just the first line.
Closes #27274
- - - - -
1f096790 by Alan Zimmerman at 2026-05-23T18:43:20-04:00
EPA: Fix exact printing namespace-specified wildcards
Ensures correct printing of imports of the form
import Data.Bool (data True(data ..))
import Data.Bool (data True(type ..))
Closes #27291
- - - - -
56ada7c0 by Mrjtjmn at 2026-05-23T18:44:19-04:00
Fix ambiguous syntax of BangPatterns in users guide
Update documentation for the BangPatterns extension to specify
how surrounding whitespace affects interpretation of `!`.
* Only when there is whitespace before `!` and no whitespace after,
it is recognized as a BangPattern.
* Other cases `⟨varid⟩!⟨varid⟩`, `⟨varid⟩ ! ⟨varid⟩`, `⟨varid⟩! ⟨varid⟩`
are treated as infix operators.
- - - - -
579aa0b7 by Simon Jakobi at 2026-05-25T16:31:26-04:00
Ensure that SetOps.{minusList,unionListsOrd} can be specialized
...by marking them INLINABLE. Haddock allocates 0.1–0.3% less as a
result.
This also removes some redundant constraints on unionListsOrd.
- - - - -
cccf45da by Cheng Shao at 2026-05-25T16:32:13-04:00
wasm: ensure post-linker output is synchronous ESM
This patch fixes wasm backend's post-linker output script to ensure
it's synchronous ESM and doesn't use top-level await, which doesn't
work in ServiceWorkers. Fixes #27257.
- - - - -
8db331a3 by Zubin Duggal at 2026-05-26T04:54:03-04:00
Update to semaphore-compat 2.0.0 using v2 of the protocol
On Linux and other POSIX platforms, GHC's -jsem jobserver client now
speaks v2 of the semaphore-compat protocol, which uses Unix domain
sockets in place of POSIX named semaphores. This avoids the libc-ABI
issues that affected the old implementation. Windows is unaffected
and continues to use the v1 protocol (Win32 named semaphores); its
reported protocol version remains v1.
When GHC receives a -jsem name whose protocol version it does not
support, it emits a -Wsemaphore-version-mismatch warning and falls
back to -j<N> rather than crashing. ghc --info exposes the supported
version in a new "Semaphore version" entry so cabal-install can detect
a mismatch before invoking GHC.
Users on a cabal-install that predates the v2 update will continue to
build successfully on Linux/POSIX, but will lose the cross-process
-jsem coordination and fall back to -j<N> per GHC invocation. Users
must upgrade to a cabal-install that supports protocol v2 to recover
full parallelism.
Also fix a leak in cleanupSem (#27253): cleanupSem used to snapshot
heldTokens and release them before killing the loop, while the loop's
in-flight acquire/release children could still be mutating it.
Cleanup now runs inside the loop's own exit handler, after draining
the active child via a new activeChild TVar, so the snapshot has no
concurrent mutator.
See also:
- GHC proposal amendment: https://github.com/ghc-proposals/ghc-proposals/pull/673
- cabal-install patch: https://github.com/haskell/cabal/pull/11628
- semaphore-compat MR: https://gitlab.haskell.org/ghc/semaphore-compat/-/merge_requests/8
Bump semaphore-compat submodule to 2.0.0
Fixes #25087 and #27253
- - - - -
17be4f1f by Alan Zimmerman at 2026-05-26T04:54:52-04:00
EPA: Record semicolons in HsModifier
Ensure the semi colons are captured in the ParsedSource for code like
%True;; %False;
instance C D
It makes HsModifier (and hence HsModifierOf) LocatedA, so the semi
colons can be recorded as [TrailingAnn]
Also rename pprHsModifiers to pprLHsModifiers to match.
Closes #27294
- - - - -
8f991755 by fendor at 2026-05-26T11:02:52-04:00
Revert prog003 acceptance
We thought the commit 286f1adff3e78d775ff325caff71d0cee25d710b fixed the
test, but due to changes to ghci, modules loaded during the GHCi
session, the test was actually no longer testing what it set out to do,
"fixing" the broken test.
As modules are added to the `interactive-session` home unit, the object code needs
to be compiled with `-this-unit-id interactive-session`, otherwise the
object code won't be used.
Once this has been fixed in the test, the test fails as expected again.
- - - - -
277a3687 by mangoiv at 2026-05-26T11:03:40-04:00
libraries/process: bump submodule to v1.6.29.0
This submodule bump resolves a segfault on macos 15.
Fixes #27144
- - - - -
6779bb0c by mangoiv at 2026-05-26T11:03:40-04:00
libraries/unix: in submodule, don't pick branch 2.7
The 2.7 branch is outdated and the module has been advanced far beyond
it anyway, so remove that line.
- - - - -
4a645683 by Simon Peyton Jones at 2026-05-27T21:41:59-04:00
Trim the continuation in mkDupableContWithDmds
When there are no remaining argument demands, it means the application
is bottoming. In this case, we can trim the continuation to avoid the
panic that was observed in #27261.
See Note [Trimming the continuation for bottoming functions] in
GHC.Core.Opt.Simplify.Iteration.
- - - - -
8ab506ff by Cheng Shao at 2026-05-27T21:42:47-04:00
ghci: fix module name string lifetime in hs_hpc_module invocation
This patch makes hpcAddModule pass a properly malloced module name
string to hs_hpc_module, instead of using useAsCString which causes
use-after-free of module name string. Fixes #27297.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
b0233814 by sheaf at 2026-05-27T21:43:31-04:00
Relax acceptance threshold for T10421
As seen in #27289, the 1% acceptance threshold for this text was
overly narrow, resulting in spurious test failures. This commit widens
the acceptance threshold to 2%. Fixes #27289.
- - - - -
2befd49d by Simon Jakobi at 2026-05-28T13:18:15+02:00
compiler: use nubOrd from containers
Address #27103 by replacing GHC.Utils.Misc.ordNub[On] with
Data.Containers.ListUtils.nubOrd[On].
Note that nubOrd suffers from a small inefficiency, a fix for which
will be included in the next containers release:
https://github.com/haskell/containers/issues/1202
- - - - -
293 changed files:
- .gitmodules
- + changelog.d/T26979
- + changelog.d/T27202
- + changelog.d/T27261
- + changelog.d/bump-process
- changelog.d/dynamic-trace-flags
- + changelog.d/elem-via-foldr-27096
- + changelog.d/ghc-pkg-faster-closure
- + changelog.d/ipe-event-class
- + changelog.d/jobserver-leak-fix
- + changelog.d/lib-add-tuple-tyfam-27179
- + changelog.d/no-more-timer-signal
- + changelog.d/rts_symlinks.md
- + changelog.d/semaphore-v2
- + changelog.d/wasm-fix-serviceworker
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/CmmToAsm/BlockLayout.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Core/Opt/FloatIn.hs
- compiler/GHC/Core/Opt/FloatOut.hs
- compiler/GHC/Core/Opt/Monad.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Data/List/SetOps.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeSem.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Foreign/JavaScript.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Linker/Unit.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/Types.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Settings/Constants.hs
- compiler/GHC/Stg/Pipeline.hs
- compiler/GHC/StgToJS/Ids.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Name/Cache.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/Supply.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Misc.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/stolen_syntax.rst
- docs/users_guide/exts/template_haskell.rst
- docs/users_guide/profiling.rst
- docs/users_guide/runtime_control.rst
- docs/users_guide/using-warnings.rst
- docs/users_guide/using.rst
- ghc/GHCi/UI.hs
- ghc/Main.hs
- hadrian/src/Flavour.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- libraries/base/changelog.md
- libraries/base/src/Control/Exception.hs
- libraries/base/src/Control/Monad/IO/Class.hs
- libraries/base/src/Data/Data.hs
- libraries/base/src/Data/Fixed.hs
- libraries/base/src/Data/List/NonEmpty.hs
- libraries/base/src/Data/Version.hs
- libraries/base/src/GHC/Base.hs
- libraries/base/src/GHC/ByteOrder.hs
- libraries/base/src/GHC/Exts.hs
- libraries/base/src/Numeric.hs
- libraries/base/src/System/IO.hs
- libraries/base/src/System/Timeout.hs
- libraries/base/tests/perf/ElemNoFusion_O1.stderr
- libraries/base/tests/perf/ElemNoFusion_O2.stderr
- + libraries/ghc-boot/GHC/Data/ShortByteString.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghc-experimental/src/Data/Sum/Experimental.hs
- libraries/ghc-experimental/src/Data/Tuple/Experimental.hs
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Exts.hs
- libraries/ghc-internal/src/GHC/Internal/List.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
- libraries/ghc-internal/src/GHC/Internal/Types.hs
- libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Run.hs
- libraries/process
- libraries/semaphore-compat
- m4/ghc_toolchain.m4
- rts/IPE.c
- rts/RtsFlags.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/include/rts/Flags.h
- testsuite/tests/codeGen/should_compile/T25177.stderr
- + testsuite/tests/codeGen/should_gen_asm/aarch64-shl-subword.asm
- + testsuite/tests/codeGen/should_gen_asm/aarch64-shl-subword.hs
- + testsuite/tests/codeGen/should_gen_asm/aarch64-ushr-subword.asm
- + testsuite/tests/codeGen/should_gen_asm/aarch64-ushr-subword.hs
- testsuite/tests/codeGen/should_gen_asm/all.T
- + testsuite/tests/codeGen/should_run/aarch64-subword-ops.hs
- + testsuite/tests/codeGen/should_run/aarch64-subword-ops.stdout
- + testsuite/tests/codeGen/should_run/aarch64-ushr-subword-run.hs
- + testsuite/tests/codeGen/should_run/aarch64-ushr-subword-run.stdout
- testsuite/tests/codeGen/should_run/all.T
- testsuite/tests/deSugar/should_compile/T13208.stdout
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/driver/fat-iface/fat014.stdout
- + testsuite/tests/ghc-api/T27273.hs
- testsuite/tests/ghc-api/all.T
- + testsuite/tests/ghci/prog-mhu006/Makefile
- + testsuite/tests/ghci/prog-mhu006/a/A.hs
- + testsuite/tests/ghci/prog-mhu006/all.T
- + testsuite/tests/ghci/prog-mhu006/b/B.hs
- + testsuite/tests/ghci/prog-mhu006/prog-mhu006a.script
- + testsuite/tests/ghci/prog-mhu006/prog-mhu006a.stdout
- + testsuite/tests/ghci/prog-mhu006/unitA
- + testsuite/tests/ghci/prog-mhu006/unitB
- testsuite/tests/ghci/prog003/prog003.script
- testsuite/tests/ghci/prog018/prog018.stdout
- testsuite/tests/ghci/prog020/Makefile
- testsuite/tests/ghci/prog020/all.T
- testsuite/tests/ghci/prog020/ghci.prog020.script → testsuite/tests/ghci/prog020/ghci.prog020a.script
- testsuite/tests/ghci/prog020/ghci.prog020.stderr → testsuite/tests/ghci/prog020/ghci.prog020a.stderr
- testsuite/tests/ghci/prog020/ghci.prog020.stdout → testsuite/tests/ghci/prog020/ghci.prog020a.stdout
- + testsuite/tests/ghci/prog020/ghci.prog020b.script
- + testsuite/tests/ghci/prog020/ghci.prog020b.stderr
- + testsuite/tests/ghci/prog020/ghci.prog020b.stdout
- + testsuite/tests/ghci/prog023/Makefile
- + testsuite/tests/ghci/prog023/all.T
- + testsuite/tests/ghci/prog023/prog023a.script
- + testsuite/tests/ghci/prog023/prog023a.stdout
- + testsuite/tests/ghci/prog023/prog023b.script
- + testsuite/tests/ghci/prog023/prog023b.stdout
- + testsuite/tests/ghci/prog023/src/A.hs
- + testsuite/tests/ghci/prog024/Makefile
- + testsuite/tests/ghci/prog024/all.T
- + testsuite/tests/ghci/prog024/prog024a.script
- + testsuite/tests/ghci/prog024/prog024a.stdout
- + testsuite/tests/ghci/prog024/prog024b.script
- + testsuite/tests/ghci/prog024/prog024b.stdout
- + testsuite/tests/ghci/prog024/prog024c.script
- + testsuite/tests/ghci/prog024/prog024c.stderr
- + testsuite/tests/ghci/prog024/prog024c.stdout
- + testsuite/tests/ghci/prog024/prog024d.script
- + testsuite/tests/ghci/prog024/prog024d.stderr
- + testsuite/tests/ghci/prog024/prog024d.stdout
- + testsuite/tests/ghci/prog024/prog024e.script
- + testsuite/tests/ghci/prog024/prog024e.stdout
- + testsuite/tests/ghci/prog024/prog024f.script
- + testsuite/tests/ghci/prog024/prog024f.stdout
- + testsuite/tests/ghci/prog024/src/A.hs
- + testsuite/tests/ghci/prog024/src/B.hs
- + testsuite/tests/ghci/prog025/Makefile
- + testsuite/tests/ghci/prog025/a/A.hs
- + testsuite/tests/ghci/prog025/all.T
- + testsuite/tests/ghci/prog025/prog025a.script
- + testsuite/tests/ghci/prog025/prog025a.stdout
- + testsuite/tests/ghci/prog025/prog025b.script
- + testsuite/tests/ghci/prog025/prog025b.stdout
- + testsuite/tests/ghci/prog025/testpkg/Test.hs
- + testsuite/tests/ghci/prog025/testpkg/testpkg-0.1.0.0.pkg
- + testsuite/tests/ghci/prog025/testpkg/testpkg-0.2.0.0.pkg
- + testsuite/tests/ghci/prog025/unitA
- testsuite/tests/ghci/scripts/ListTuplePunsPprNoAbbrevTuple.stdout
- testsuite/tests/ghci/scripts/T13997.stdout
- testsuite/tests/ghci/scripts/T1914.stdout
- testsuite/tests/ghci/scripts/T20217.stdout
- testsuite/tests/ghci/scripts/T8042.stdout
- testsuite/tests/ghci/scripts/T8042recomp.stdout
- testsuite/tests/ghci/scripts/all.T
- testsuite/tests/ghci/should_run/T10920.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/linters/notes.stdout
- testsuite/tests/numeric/should_compile/T15547.stderr
- testsuite/tests/numeric/should_compile/T20347.stderr
- testsuite/tests/numeric/should_compile/T20374.stderr
- testsuite/tests/numeric/should_compile/T20376.stderr
- testsuite/tests/parser/should_compile/ListTuplePunsSuccess1.hs
- testsuite/tests/parser/should_compile/all.T
- + testsuite/tests/parser/should_fail/ListTuplePunsFail6.hs
- + testsuite/tests/parser/should_fail/ListTuplePunsFail6.stderr
- testsuite/tests/parser/should_fail/all.T
- testsuite/tests/parser/should_run/ListTuplePunsConstraints.hs
- + testsuite/tests/perf/compiler/T26989.hs
- + testsuite/tests/perf/compiler/T26989a.hs
- testsuite/tests/perf/compiler/all.T
- testsuite/tests/printer/Makefile
- testsuite/tests/printer/PprModifiers.hs
- + testsuite/tests/printer/PprQualifiedStrings.hs
- testsuite/tests/printer/T18052a.stderr
- + testsuite/tests/printer/Test27291.hs
- testsuite/tests/printer/all.T
- testsuite/tests/profiling/should_run/callstack001.stdout
- + testsuite/tests/rts/T25275/DebugIpe.hs
- + testsuite/tests/rts/T25275/T25275_A.stdout
- + testsuite/tests/rts/T25275/T25275_B.stdout
- + testsuite/tests/rts/T25275/T25275_C.stdout
- + testsuite/tests/rts/T25275/T25275_D.stdout
- + testsuite/tests/rts/T25275/TraceIpe.hs
- + testsuite/tests/rts/T25275/all.T
- testsuite/tests/simplCore/should_compile/DsSpecPragmas.stderr
- testsuite/tests/simplCore/should_compile/RewriteHigherOrderPatterns.stderr
- testsuite/tests/simplCore/should_compile/T15205.stderr
- testsuite/tests/simplCore/should_compile/T18668.stderr
- testsuite/tests/simplCore/should_compile/T19246.stderr
- testsuite/tests/simplCore/should_compile/T19599.stderr
- testsuite/tests/simplCore/should_compile/T19599a.stderr
- testsuite/tests/simplCore/should_compile/T21917.stderr
- testsuite/tests/simplCore/should_compile/T23074.stderr
- testsuite/tests/simplCore/should_compile/T24359a.stderr
- testsuite/tests/simplCore/should_compile/T25160.stderr
- testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-32
- testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-64
- testsuite/tests/simplCore/should_compile/T26051.stderr
- testsuite/tests/simplCore/should_compile/T26116.stderr
- + testsuite/tests/simplCore/should_compile/T27261.hs
- + testsuite/tests/simplCore/should_compile/T27261_aux.hs
- testsuite/tests/simplCore/should_compile/T8331.stderr
- testsuite/tests/simplCore/should_compile/T8848a.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_compile/spec004.stderr
- testsuite/tests/typecheck/should_compile/T13032.stderr
- + testsuite/tests/typecheck/should_compile/T23135.hs
- testsuite/tests/typecheck/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Program.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- utils/jsffi/prelude.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/83407b0b4013befb565825e23b7f02…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/83407b0b4013befb565825e23b7f02…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fendor/drop-preloadclosure-from-unitstate] Drop `preloadClosure` from `UnitState`
by Hannes Siebenhandl (@fendor) 28 May '26
by Hannes Siebenhandl (@fendor) 28 May '26
28 May '26
Hannes Siebenhandl pushed to branch wip/fendor/drop-preloadclosure-from-unitstate at Glasgow Haskell Compiler / GHC
Commits:
9b1d070e by fendor at 2026-05-28T12:50:13+02:00
Drop `preloadClosure` from `UnitState`
It is always hard-coded to the same value.
Backpack Unit instantiation isn't using it any more.
Allows us to simplify the API and get rid of `improveUnit`.
- - - - -
7 changed files:
- + changelog.d/T27308
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Unit.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
Changes:
=====================================
changelog.d/T27308
=====================================
@@ -0,0 +1,10 @@
+section: compiler
+synopsis: Drop `preloadClosure` from `UnitState`
+issues: #27308
+mrs: !16108
+
+description: {
+ Drop `preloadClosure` from `UnitState` as it is always set to the empty set.
+ This allows to simplify the `UnitState` and related functions.
+}
+
=====================================
compiler/GHC/Driver/Backpack.hs
=====================================
@@ -241,7 +241,6 @@ withBkpSession cid insts deps session_type do_this = do
-- Synthesize the flags
, packageFlags = packageFlags dflags ++ map (\(uid0, rn) ->
let uid = unwireUnit unit_state
- $ improveUnit unit_state
$ renameHoleUnit unit_state (listToUFM insts) uid0
in ExposePackage
(showSDoc dflags
@@ -310,19 +309,16 @@ buildUnit session cid insts lunit = do
-- The compilation dependencies are just the appropriately filled
-- in unit IDs which must be compiled before we can compile.
let hsubst = listToUFM insts
- deps0 = map (renameHoleUnit (hsc_units hsc_env) hsubst) raw_deps
+ deps = map (renameHoleUnit (hsc_units hsc_env) hsubst) raw_deps
-- Build dependencies OR make sure they make sense. BUT NOTE,
-- we can only check the ones that are fully filled; the rest
-- we have to defer until we've typechecked our local signature.
-- TODO: work this into GHC.Driver.Make!!
- forM_ (zip [1..] deps0) $ \(i, dep) ->
+ forM_ (zip [1..] deps) $ \(i, dep) ->
case session of
TcSession -> return ()
- _ -> compileInclude (length deps0) (i, dep)
-
- -- IMPROVE IT
- let deps = map (improveUnit (hsc_units hsc_env)) deps0
+ _ -> compileInclude (length deps) (i, dep)
mb_old_eps <- case session of
TcSession -> fmap Just getEpsGhc
=====================================
compiler/GHC/Iface/Load.hs
=====================================
@@ -914,13 +914,13 @@ findAndReadIface hsc_env doc_str mod wanted_mod hi_boot_file = do
&& not (isOneShot (ghcMode dflags))
then return (Failed (HomeModError mod loc))
else do
- r <- read_file hooks logger name_cache unit_state dflags wanted_mod (ml_hi_file loc)
+ r <- read_file hooks logger name_cache dflags wanted_mod (ml_hi_file loc)
case r of
Failed err
-> return (Failed $ BadIfaceFile err)
Succeeded (iface,_fp)
-> do
- r2 <- load_dynamic_too_maybe hooks logger name_cache unit_state
+ r2 <- load_dynamic_too_maybe hooks logger name_cache
(setDynamicNow dflags) wanted_mod
iface loc
case r2 of
@@ -936,20 +936,20 @@ findAndReadIface hsc_env doc_str mod wanted_mod hi_boot_file = do
err
-- | Check if we need to try the dynamic interface for -dynamic-too
-load_dynamic_too_maybe :: Hooks -> Logger -> NameCache -> UnitState -> DynFlags
+load_dynamic_too_maybe :: Hooks -> Logger -> NameCache -> DynFlags
-> Module -> ModIface -> ModLocation
-> IO (MaybeErr MissingInterfaceError ())
-load_dynamic_too_maybe hooks logger name_cache unit_state dflags wanted_mod iface loc
+load_dynamic_too_maybe hooks logger name_cache dflags wanted_mod iface loc
-- Indefinite interfaces are ALWAYS non-dynamic.
| not (moduleIsDefinite (mi_module iface)) = return (Succeeded ())
- | gopt Opt_BuildDynamicToo dflags = load_dynamic_too hooks logger name_cache unit_state dflags wanted_mod iface loc
+ | gopt Opt_BuildDynamicToo dflags = load_dynamic_too hooks logger name_cache dflags wanted_mod iface loc
| otherwise = return (Succeeded ())
-load_dynamic_too :: Hooks -> Logger -> NameCache -> UnitState -> DynFlags
+load_dynamic_too :: Hooks -> Logger -> NameCache -> DynFlags
-> Module -> ModIface -> ModLocation
-> IO (MaybeErr MissingInterfaceError ())
-load_dynamic_too hooks logger name_cache unit_state dflags wanted_mod iface loc = do
- read_file hooks logger name_cache unit_state dflags wanted_mod (ml_dyn_hi_file loc) >>= \case
+load_dynamic_too hooks logger name_cache dflags wanted_mod iface loc = do
+ read_file hooks logger name_cache dflags wanted_mod (ml_dyn_hi_file loc) >>= \case
Succeeded (dynIface, _)
| mi_mod_hash iface == mi_mod_hash dynIface
-> return (Succeeded ())
@@ -963,10 +963,10 @@ load_dynamic_too hooks logger name_cache unit_state dflags wanted_mod iface loc
-read_file :: Hooks -> Logger -> NameCache -> UnitState -> DynFlags
+read_file :: Hooks -> Logger -> NameCache -> DynFlags
-> Module -> FilePath
-> IO (MaybeErr ReadInterfaceError (ModIface, FilePath))
-read_file hooks logger name_cache unit_state dflags wanted_mod file_path = do
+read_file hooks logger name_cache dflags wanted_mod file_path = do
-- Figure out what is recorded in mi_module. If this is
-- a fully definite interface, it'll match exactly, but
@@ -975,7 +975,7 @@ read_file hooks logger name_cache unit_state dflags wanted_mod file_path = do
case getModuleInstantiation wanted_mod of
(_, Nothing) -> wanted_mod
(_, Just indef_mod) ->
- instModuleToModule unit_state
+ instModuleToModule
(uninstantiateInstantiatedModule indef_mod)
read_result <- readIface hooks logger dflags name_cache wanted_mod' file_path
case read_result of
=====================================
compiler/GHC/Iface/Recomp.hs
=====================================
@@ -620,7 +620,7 @@ checkMergedSignatures hsc_env mod_summary self_recomp = do
new_merged = case lookupUniqMap (requirementContext unit_state)
(ms_mod_name mod_summary) of
Nothing -> []
- Just r -> sort $ map (instModuleToModule unit_state) r
+ Just r -> sort $ map instModuleToModule r
if old_merged == new_merged
then up_to_date logger (text "signatures to merge in unchanged" $$ ppr new_merged)
else return $ needsRecompileBecause SigsMergeChanged
=====================================
compiler/GHC/Unit.hs
=====================================
@@ -226,8 +226,7 @@ on-the-fly:
A 'VirtUnit' may be indefinite or definite, it depends on whether some holes
remain in the instantiated unit OR in the instantiating units (recursively).
Having a fully instantiated (i.e. definite) virtual unit can lead to some issues
-if there is a matching compiled unit in the preload closure. See Note [VirtUnit
-to RealUnit improvement]
+if there is a matching compiled unit in the preload closure.
Unit database and indefinite units
----------------------------------
@@ -314,32 +313,6 @@ field in the SDocContext to pretty-print.
(i.e. GHC doesn't correctly call `pprWithUnitState` before pretty-printing a
UnitId), that's what will be shown to the user so it's no big deal.
-
-Note [VirtUnit to RealUnit improvement]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Over the course of instantiating VirtUnits on the fly while typechecking an
-indefinite library, we may end up with a fully instantiated VirtUnit. I.e.
-one that could be compiled and installed in the database. During
-type-checking we generate a virtual UnitId for it, say "abc".
-
-Now the question is: do we have a matching installed unit in the database?
-Suppose we have one with UnitId "xyz" (provided by Cabal so we don't know how
-to generate it). The trouble is that if both units end up being used in the
-same type-checking session, their names won't match (e.g. "abc:M.X" vs
-"xyz:M.X").
-
-As we want them to match we just replace the virtual unit with the installed
-one: for some reason this is called "improvement".
-
-There is one last niggle: improvement based on the unit database means
-that we might end up developing on a unit that is not transitively
-depended upon by the units the user specified directly via command line
-flags. This could lead to strange and difficult to understand bugs if those
-instantiations are out of date. The solution is to only improve a
-unit id if the new unit id is part of the 'preloadClosure'; i.e., the
-closure of all the units which were explicitly specified.
-
Note [Representation of module/name variables]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In our ICFP'16, we use <A> to represent module holes, and {A.T} to represent
=====================================
compiler/GHC/Unit/State.hs
=====================================
@@ -7,7 +7,6 @@ module GHC.Unit.State (
-- * Reading the package config, and processing cmdline args
UnitState(..),
- PreloadUnitClosure,
UnitDatabase (..),
UnitErr (..),
emptyUnitState,
@@ -29,7 +28,6 @@ module GHC.Unit.State (
lookupPackageName,
resolvePackageImport,
- improveUnit,
searchPackageId,
listVisibleModuleNames,
lookupModuleInAllUnits,
@@ -89,7 +87,6 @@ import GHC.Unit.Home
import GHC.Types.Unique.FM
import GHC.Types.Unique.DFM
-import GHC.Types.Unique.Set
import GHC.Types.Unique.DSet
import GHC.Types.Unique.Map
import GHC.Types.Unique
@@ -267,8 +264,6 @@ originEmpty :: ModuleOrigin -> Bool
originEmpty (ModOrigin Nothing [] [] False) = True
originEmpty _ = False
-type PreloadUnitClosure = UniqSet UnitId
-
-- | 'UniqFM' map from 'Unit' to a 'UnitVisibility'.
type VisibilityMap = UniqMap Unit UnitVisibility
@@ -431,13 +426,6 @@ data UnitState = UnitState {
-- may have the 'exposed' flag be 'False'.)
unitInfoMap :: UnitInfoMap,
- -- | The set of transitively reachable units according
- -- to the explicitly provided command line arguments.
- -- A fully instantiated VirtUnit may only be replaced by a RealUnit from
- -- this set.
- -- See Note [VirtUnit to RealUnit improvement]
- preloadClosure :: PreloadUnitClosure,
-
-- | A mapping of 'PackageName' to 'UnitId'. If several units have the same
-- package name (e.g. different instantiations), then we return one of them...
-- This is used when users refer to packages in Backpack includes.
@@ -490,7 +478,6 @@ data UnitState = UnitState {
emptyUnitState :: UnitState
emptyUnitState = UnitState {
unitInfoMap = emptyUniqMap,
- preloadClosure = emptyUniqSet,
packageNameMap = emptyUFM,
wireMap = emptyUniqMap,
unwireMap = emptyUniqMap,
@@ -516,7 +503,7 @@ type UnitInfoMap = UniqMap UnitId UnitInfo
-- | Find the unit we know about with the given unit, if any
lookupUnit :: UnitState -> Unit -> Maybe UnitInfo
-lookupUnit pkgs = lookupUnit' (allowVirtualUnits pkgs) (unitInfoMap pkgs) (preloadClosure pkgs)
+lookupUnit pkgs = lookupUnit' (allowVirtualUnits pkgs) (unitInfoMap pkgs)
-- | A more specialized interface, which doesn't require a 'UnitState' (so it
-- can be used while we're initializing 'DynFlags')
@@ -524,16 +511,15 @@ lookupUnit pkgs = lookupUnit' (allowVirtualUnits pkgs) (unitInfoMap pkgs) (prelo
-- Parameters:
-- * a boolean specifying whether or not to look for on-the-fly renamed interfaces
-- * a 'UnitInfoMap'
--- * a 'PreloadUnitClosure'
-lookupUnit' :: Bool -> UnitInfoMap -> PreloadUnitClosure -> Unit -> Maybe UnitInfo
-lookupUnit' allowOnTheFlyInst pkg_map closure u = case u of
+lookupUnit' :: Bool -> UnitInfoMap -> Unit -> Maybe UnitInfo
+lookupUnit' allowOnTheFlyInst pkg_map u = case u of
HoleUnit -> error "Hole unit"
RealUnit i -> lookupUniqMap pkg_map (unDefinite i)
VirtUnit i
| allowOnTheFlyInst
-> -- lookup UnitInfo of the indefinite unit to be instantiated and
-- instantiate it on-the-fly
- fmap (renameUnitInfo pkg_map closure (instUnitInsts i))
+ fmap (renameUnitInfo pkg_map (instUnitInsts i))
(lookupUniqMap pkg_map (instUnitInstanceOf i))
| otherwise
@@ -907,7 +893,6 @@ applyTrustFlag prec_map unusable pkgs flag =
applyPackageFlag
:: UnitPrecedenceMap
-> UnitInfoMap
- -> PreloadUnitClosure
-> UnusableUnits
-> Bool -- if False, if you expose a package, it implicitly hides
-- any previously exposed packages with the same name
@@ -916,10 +901,10 @@ applyPackageFlag
-> PackageFlag -- flag to apply
-> MaybeErr UnitErr VisibilityMap -- Now exposed
-applyPackageFlag prec_map pkg_map closure unusable no_hide_others pkgs vm flag =
+applyPackageFlag prec_map pkg_map unusable no_hide_others pkgs vm flag =
case flag of
ExposePackage _ arg (ModRenaming b rns) ->
- case findPackages prec_map pkg_map closure arg pkgs unusable of
+ case findPackages prec_map pkg_map arg pkgs unusable of
Left ps -> Failed (PackageFlagErr flag ps)
Right (p:_) -> Succeeded vm'
where
@@ -983,7 +968,7 @@ applyPackageFlag prec_map pkg_map closure unusable no_hide_others pkgs vm flag =
_ -> panic "applyPackageFlag"
HidePackage str ->
- case findPackages prec_map pkg_map closure (PackageArg str) pkgs unusable of
+ case findPackages prec_map pkg_map (PackageArg str) pkgs unusable of
Left ps -> Failed (PackageFlagErr flag ps)
Right ps -> Succeeded $ foldl' delFromUniqMap vm (map mkUnit ps)
@@ -992,12 +977,11 @@ applyPackageFlag prec_map pkg_map closure unusable no_hide_others pkgs vm flag =
-- if the 'UnitArg' has a renaming associated with it.
findPackages :: UnitPrecedenceMap
-> UnitInfoMap
- -> PreloadUnitClosure
-> PackageArg -> [UnitInfo]
-> UnusableUnits
-> Either [(UnitInfo, UnusableUnitReason)]
[UnitInfo]
-findPackages prec_map pkg_map closure arg pkgs unusable
+findPackages prec_map pkg_map arg pkgs unusable
= let ps = mapMaybe (finder arg) pkgs
in if null ps
then Left (mapMaybe (\(x,y) -> finder arg x >>= \x' -> return (x',y))
@@ -1015,7 +999,7 @@ findPackages prec_map pkg_map closure arg pkgs unusable
-> Just p
VirtUnit inst
| instUnitInstanceOf inst == unitId p
- -> Just (renameUnitInfo pkg_map closure (instUnitInsts inst) p)
+ -> Just (renameUnitInfo pkg_map (instUnitInsts inst) p)
_ -> Nothing
selectPackages :: UnitPrecedenceMap -> PackageArg -> [UnitInfo]
@@ -1030,10 +1014,10 @@ selectPackages prec_map arg pkgs unusable
else Right (sortByPreference prec_map ps, rest)
-- | Rename a 'UnitInfo' according to some module instantiation.
-renameUnitInfo :: UnitInfoMap -> PreloadUnitClosure -> [(ModuleName, Module)] -> UnitInfo -> UnitInfo
-renameUnitInfo pkg_map closure insts conf =
+renameUnitInfo :: UnitInfoMap -> [(ModuleName, Module)] -> UnitInfo -> UnitInfo
+renameUnitInfo pkg_map insts conf =
let hsubst = listToUFM insts
- smod = renameHoleModule' pkg_map closure hsubst
+ smod = renameHoleModule' pkg_map hsubst
new_insts = map (\(k,v) -> (k,smod v)) (unitInstantiations conf)
in conf {
unitInstantiations = new_insts,
@@ -1631,7 +1615,7 @@ mkUnitState logger cfg = do
-- user tries to enable an unusable package, we should let them know.
--
vis_map2 <- mayThrowUnitErr
- $ foldM (applyPackageFlag prec_map prelim_pkg_db emptyUniqSet unusable
+ $ foldM (applyPackageFlag prec_map prelim_pkg_db unusable
(unitConfigHideAll cfg) pkgs1)
vis_map1 other_flags
@@ -1660,7 +1644,7 @@ mkUnitState logger cfg = do
| otherwise = vis_map2
plugin_vis_map2
<- mayThrowUnitErr
- $ foldM (applyPackageFlag prec_map prelim_pkg_db emptyUniqSet unusable
+ $ foldM (applyPackageFlag prec_map prelim_pkg_db unusable
hide_plugin_pkgs pkgs1)
plugin_vis_map1
(reverse (unitConfigFlagsPlugins cfg))
@@ -1712,7 +1696,7 @@ mkUnitState logger cfg = do
$ closeUnitDeps pkg_db
$ zip (map toUnitId preload3) (repeat Nothing)
- let mod_map1 = mkModuleNameProvidersMap logger cfg pkg_db emptyUniqSet vis_map
+ let mod_map1 = mkModuleNameProvidersMap logger cfg pkg_db vis_map
mod_map2 = mkUnusableModuleNameProvidersMap unusable
mod_map = mod_map2 `plusUniqMap` mod_map1
@@ -1722,9 +1706,8 @@ mkUnitState logger cfg = do
, explicitUnits = explicit_pkgs
, homeUnitDepends = home_unit_deps
, unitInfoMap = pkg_db
- , preloadClosure = emptyUniqSet
, moduleNameProvidersMap = mod_map
- , pluginModuleNameProvidersMap = mkModuleNameProvidersMap logger cfg pkg_db emptyUniqSet plugin_vis_map
+ , pluginModuleNameProvidersMap = mkModuleNameProvidersMap logger cfg pkg_db plugin_vis_map
, packageNameMap = pkgname_map
, wireMap = wired_map
, unwireMap = listToUniqMap [ (v,k) | (k,v) <- nonDetUniqMapToList wired_map ]
@@ -1764,10 +1747,9 @@ mkModuleNameProvidersMap
:: Logger
-> UnitConfig
-> UnitInfoMap
- -> PreloadUnitClosure
-> VisibilityMap
-> ModuleNameProvidersMap
-mkModuleNameProvidersMap logger cfg pkg_map closure vis_map =
+mkModuleNameProvidersMap logger cfg pkg_map vis_map =
-- What should we fold on? Both situations are awkward:
--
-- * Folding on the visibility map means that we won't create
@@ -1839,7 +1821,7 @@ mkModuleNameProvidersMap logger cfg pkg_map closure vis_map =
hiddens = [(m, mkModMap pk m ModHidden) | m <- hidden_mods]
pk = mkUnit pkg
- unit_lookup uid = lookupUnit' (unitConfigAllowVirtual cfg) pkg_map closure uid
+ unit_lookup uid = lookupUnit' (unitConfigAllowVirtual cfg) pkg_map uid
`orElse` pprPanic "unit_lookup" (ppr uid)
exposed_mods = unitExposedModules pkg
@@ -2190,44 +2172,16 @@ fsPackageName info = fs
where
PackageName fs = unitPackageName info
-
--- | Given a fully instantiated 'InstantiatedUnit', improve it into a
--- 'RealUnit' if we can find it in the package database.
-improveUnit :: UnitState -> Unit -> Unit
-improveUnit state u = improveUnit' (unitInfoMap state) (preloadClosure state) u
-
--- | Given a fully instantiated 'InstantiatedUnit', improve it into a
--- 'RealUnit' if we can find it in the package database.
-improveUnit' :: UnitInfoMap -> PreloadUnitClosure -> Unit -> Unit
-improveUnit' _ _ uid@(RealUnit _) = uid -- short circuit
-improveUnit' pkg_map closure uid =
- -- Do NOT lookup indefinite ones, they won't be useful!
- case lookupUnit' False pkg_map closure uid of
- Nothing -> uid
- Just pkg ->
- -- Do NOT improve if the indefinite unit id is not
- -- part of the closure unique set. See
- -- Note [VirtUnit to RealUnit improvement]
- if unitId pkg `elementOfUniqSet` closure
- then mkUnit pkg
- else uid
-
--- | Check the database to see if we already have an installed unit that
--- corresponds to the given 'InstantiatedUnit'.
---
--- Return a `UnitId` which either wraps the `InstantiatedUnit` unchanged or
--- references a matching installed unit.
---
--- See Note [VirtUnit to RealUnit improvement]
-instUnitToUnit :: UnitState -> InstantiatedUnit -> Unit
-instUnitToUnit state iuid =
+-- | Return a `UnitId` which either wraps the `InstantiatedUnit` unchanged.
+instUnitToUnit :: InstantiatedUnit -> Unit
+instUnitToUnit iuid =
-- NB: suppose that we want to compare the instantiated
-- unit p[H=impl:H] against p+abcd (where p+abcd
-- happens to be the existing, installed version of
-- p[H=impl:H]. If we *only* wrap in p[H=impl:H]
-- VirtUnit, they won't compare equal; only
-- after improvement will the equality hold.
- improveUnit state $ VirtUnit iuid
+ VirtUnit iuid
-- | Substitution on module variables, mapping module names to module
@@ -2239,30 +2193,30 @@ type ShHoleSubst = ModuleNameEnv Module
-- @p[A=\<A>]:B@ maps to @p[A=q():A]:B@ with @A=q():A@;
-- similarly, @\<A>@ maps to @q():A@.
renameHoleModule :: UnitState -> ShHoleSubst -> Module -> Module
-renameHoleModule state = renameHoleModule' (unitInfoMap state) (preloadClosure state)
+renameHoleModule state = renameHoleModule' (unitInfoMap state)
-- | Substitutes holes in a 'Unit', suitable for renaming when
-- an include occurs; see Note [Representation of module/name variables].
--
-- @p[A=\<A>]@ maps to @p[A=\<B>]@ with @A=\<B>@.
renameHoleUnit :: UnitState -> ShHoleSubst -> Unit -> Unit
-renameHoleUnit state = renameHoleUnit' (unitInfoMap state) (preloadClosure state)
+renameHoleUnit state = renameHoleUnit' (unitInfoMap state)
--- | Like 'renameHoleModule', but requires only 'ClosureUnitInfoMap'
+-- | Like 'renameHoleModule', but requires only 'UnitInfoMap'
-- so it can be used by "GHC.Unit.State".
-renameHoleModule' :: UnitInfoMap -> PreloadUnitClosure -> ShHoleSubst -> Module -> Module
-renameHoleModule' pkg_map closure env m
+renameHoleModule' :: UnitInfoMap -> ShHoleSubst -> Module -> Module
+renameHoleModule' pkg_map env m
| not (isHoleModule m) =
- let uid = renameHoleUnit' pkg_map closure env (moduleUnit m)
+ let uid = renameHoleUnit' pkg_map env (moduleUnit m)
in mkModule uid (moduleName m)
| Just m' <- lookupUFM env (moduleName m) = m'
-- NB m = <Blah>, that's what's in scope.
| otherwise = m
--- | Like 'renameHoleUnit, but requires only 'ClosureUnitInfoMap'
+-- | Like 'renameHoleUnit', but requires only 'UnitInfoMap'
-- so it can be used by "GHC.Unit.State".
-renameHoleUnit' :: UnitInfoMap -> PreloadUnitClosure -> ShHoleSubst -> Unit -> Unit
-renameHoleUnit' pkg_map closure env uid =
+renameHoleUnit' :: UnitInfoMap -> ShHoleSubst -> Unit -> Unit
+renameHoleUnit' pkg_map env uid =
case uid of
(VirtUnit
InstantiatedUnit{ instUnitInstanceOf = cid
@@ -2270,20 +2224,15 @@ renameHoleUnit' pkg_map closure env uid =
, instUnitHoles = fh })
-> if isNullUFM (intersectUFM_C const (udfmToUfm (getUniqDSet fh)) env)
then uid
- -- Functorially apply the substitution to the instantiation,
- -- then check the 'ClosureUnitInfoMap' to see if there is
- -- a compiled version of this 'InstantiatedUnit' we can improve to.
- -- See Note [VirtUnit to RealUnit improvement]
- else improveUnit' pkg_map closure $
- mkVirtUnit cid
- (map (\(k,v) -> (k, renameHoleModule' pkg_map closure env v)) insts)
+ else mkVirtUnit cid
+ (map (\(k,v) -> (k, renameHoleModule' pkg_map env v)) insts)
_ -> uid
-- | Injects an 'InstantiatedModule' to 'Module' (see also
-- 'instUnitToUnit'.
-instModuleToModule :: UnitState -> InstantiatedModule -> Module
-instModuleToModule pkgstate (Module iuid mod_name) =
- mkModule (instUnitToUnit pkgstate iuid) mod_name
+instModuleToModule :: InstantiatedModule -> Module
+instModuleToModule (Module iuid mod_name) =
+ mkModule (instUnitToUnit iuid) mod_name
-- | Print unit-ids with UnitInfo found in the given UnitState
pprWithUnitState :: UnitState -> SDoc -> SDoc
=====================================
compiler/GHC/Unit/Types.hs
=====================================
@@ -250,9 +250,7 @@ data GenUnit uid
--
-- This unit may be indefinite or not (i.e. with remaining holes or not). If it
-- is definite, we don't know if it has already been compiled and installed in a
--- database. Nevertheless, we have a mechanism called "improvement" to try to
--- match a fully instantiated unit with existing compiled and installed units:
--- see Note [VirtUnit to RealUnit improvement].
+-- database.
--
-- An indefinite unit identifier pretty-prints to something like
-- @p[H=<H>,A=aimpl:A>]@ (@p@ is the 'UnitId', and the
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9b1d070e3a5e593c1b76ba8eaa86ecb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9b1d070e3a5e593c1b76ba8eaa86ecb…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/davide/hadrian-aclocal_path] 4 commits: Trim the continuation in mkDupableContWithDmds
by David Eichmann (@DavidEichmann) 28 May '26
by David Eichmann (@DavidEichmann) 28 May '26
28 May '26
David Eichmann pushed to branch wip/davide/hadrian-aclocal_path at Glasgow Haskell Compiler / GHC
Commits:
4a645683 by Simon Peyton Jones at 2026-05-27T21:41:59-04:00
Trim the continuation in mkDupableContWithDmds
When there are no remaining argument demands, it means the application
is bottoming. In this case, we can trim the continuation to avoid the
panic that was observed in #27261.
See Note [Trimming the continuation for bottoming functions] in
GHC.Core.Opt.Simplify.Iteration.
- - - - -
8ab506ff by Cheng Shao at 2026-05-27T21:42:47-04:00
ghci: fix module name string lifetime in hs_hpc_module invocation
This patch makes hpcAddModule pass a properly malloced module name
string to hs_hpc_module, instead of using useAsCString which causes
use-after-free of module name string. Fixes #27297.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
b0233814 by sheaf at 2026-05-27T21:43:31-04:00
Relax acceptance threshold for T10421
As seen in #27289, the 1% acceptance threshold for this text was
overly narrow, resulting in spurious test failures. This commit widens
the acceptance threshold to 2%. Fixes #27289.
- - - - -
1127299e by David Eichmann at 2026-05-28T11:26:39+01:00
Hadrian: Autoreconf builder on windows converts env variable ACLOCAL_PATH to unix paths
This is needed to fix hadrian bindist builds on windows in the mysy2
clang64 environment
- - - - -
14 changed files:
- boot
- + changelog.d/T27261
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Utilities.hs
- + libraries/ghc-boot/GHC/Data/ShortByteString.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Run.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/simplCore/should_compile/T27261.hs
- + testsuite/tests/simplCore/should_compile/T27261_aux.hs
- testsuite/tests/simplCore/should_compile/all.T
Changes:
=====================================
boot
=====================================
@@ -54,7 +54,9 @@ def autoreconf():
if os.name == 'nt':
# Get the normalized ACLOCAL_PATH for Windows
# This is necessary since on Windows this will be a Windows
- # path, which autoreconf doesn't know doesn't know how to handle.
+ # path, which autoreconf doesn't know how to handle.
+ #
+ # This logic is duplicated in Hadrian. Specifically in hadrian/src/Rules/BinaryDist.hs
ac_local = os.getenv('ACLOCAL_PATH', '')
ac_local_arg = re.sub(r';', r':', ac_local)
ac_local_arg = re.sub(r'\\', r'/', ac_local_arg)
=====================================
changelog.d/T27261
=====================================
@@ -0,0 +1,10 @@
+section: compiler
+issues: #27261
+mrs: !16084
+synopsis:
+ Avoid a crash in ``mkDupableContWithDmds`` when given empty demands
+description:
+ The case of an empty list of remaining argument demands is now explicitly
+ handled by trimming the simplifier continuation, to avoid a compiler crash
+ of the form ``Non-exhaustive patterns in dmd : cont_dmds`` or ``expectNonEmpty``
+ in ``mkDupableContWithDmds``.
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -62,6 +62,7 @@ import GHC.Types.Var ( isTyCoVar )
import GHC.Builtin.Types.Prim( realWorldStatePrimTy )
import GHC.Builtin.Names( runRWKey, seqHashKey )
+import qualified GHC.Data.List.Infinite as Inf
import GHC.Data.Maybe ( isNothing, orElse, mapMaybe )
import GHC.Data.FastString
import GHC.Unit.Module ( moduleName )
@@ -2444,24 +2445,9 @@ rebuildCall env arg_info _cont
---------- Bottoming applications --------------
rebuildCall env (ArgInfo { ai_fun = fun, ai_args = rev_args, ai_dmds = [] }) cont
- -- When we run out of strictness args, it means
- -- that the call is definitely bottom; see GHC.Core.Opt.Simplify.Utils.mkArgInfo
- -- Then we want to discard the entire strict continuation. E.g.
- -- * case (error "hello") of { ... }
- -- * (error "Hello") arg
- -- * f (error "Hello") where f is strict
- -- etc
- -- Then, especially in the first of these cases, we'd like to discard
- -- the continuation, leaving just the bottoming expression. But the
- -- type might not be right, so we may have to add a coerce.
- | not (contIsTrivial cont) -- Only do this if there is a non-trivial
- -- continuation to discard, else we do it
- -- again and again!
- = seqType cont_ty `seq` -- See Note [Avoiding space leaks in OutType]
- return (emptyFloats env, castBottomExpr res cont_ty)
- where
- res = argInfoExpr fun rev_args
- cont_ty = contResultType cont
+ -- When we run out of demands, it means that the call is definitely bottom.
+ -- See (TC2) in Note [Trimming the continuation for bottoming functions]
+ = rebuild env (argInfoExpr fun rev_args) (mkBottomCont cont)
---------- Simplify type applications --------------
rebuildCall env info (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = cont })
@@ -4045,6 +4031,41 @@ When we have
then we can just duplicate those alts because the A and C cases
will disappear immediately. This is more direct than creating
join points and inlining them away. See #4930.
+
+Note [Trimming the continuation for bottoming functions]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Suppose
+ f :: Int -> Int -> Int
+ f x = error "urk"
+
+ foo = f 3 4
+
+f's demand signature say "after one arg I return bottom". We can drop
+the remaining arguments, thus
+
+ foo = case f 3 of {}
+
+This trimming can also be done with other continuations:
+ * case (error "hello") of { ... }
+ * f (error "Hello") where f is strict
+ etc
+
+We implement the trimming in three parts:
+
+(TC1) In `mkArgInfo`, for a bottoming function, we make a list of `RemainingArgDmds`
+ with a finite list of elements (in the example above, just one).
+
+ For comparison, note that, for non-bottoming functions, the `RemainingArgDmds`
+ always finishes with an infinite list of `topDmd`.
+
+(TC2) In `rebuildCall`, when we run out of `RemainingArgDmds` we discard the
+ remaining continuation.
+
+ After discarding the continuation, the types might not match, in which case
+ we leave behind a (case <hole> of {}) wrapper. See the call to `mkBottomCont`.
+
+(TC3) In `mkDupableContWithDmds`, we similarly discard the continuation when
+ we run out of `RemainingArgDmds`.
-}
--------------------
@@ -4079,10 +4100,10 @@ mkDupableCont env cont
= mkDupableContWithDmds (zapSubstEnv env) (repeat topDmd) cont
mkDupableContWithDmds
- :: SimplEnvIS -> [Demand] -- Demands on arguments; always infinite
+ :: SimplEnvIS -> RemainingArgDmds
-> SimplCont -> SimplM ( SimplFloats, SimplCont)
-mkDupableContWithDmds env _ cont
+mkDupableContWithDmds env remaining_dmds cont
-- Check the invariant
| assertPpr (checkSimplEnvIS env) (pprBadSimplEnvIS env) False
= pprPanic "mkDupableContWithDmds" empty
@@ -4090,6 +4111,13 @@ mkDupableContWithDmds env _ cont
| contIsDupable cont
= return (emptyFloats env, cont)
+ -- No more demands => function is definitely bottom
+ -- => simply trim the continuation
+ -- c.f. the null-demands case in `rebuildCall`
+ -- See (TC3) in Note [Trimming the continuation for bottoming functions]
+ | null remaining_dmds
+ = return (emptyFloats env, mkBottomCont cont)
+
mkDupableContWithDmds _ _ (Stop {}) = panic "mkDupableCont" -- Handled by previous eqn
mkDupableContWithDmds env dmds (CastIt { sc_co = co, sc_opt = opt, sc_cont = cont })
@@ -4134,7 +4162,8 @@ mkDupableContWithDmds env _
, thumbsUpPlanA cont
= -- Use Plan A of Note [Duplicating StrictArg]
-- pprTrace "Using plan A" (ppr (ai_fun fun) $$ text "args" <+> ppr (ai_args fun) $$ text "cont" <+> ppr cont) $
- do { let _ :| dmds = expectNonEmpty $ ai_dmds fun
+ do { let _ :| dmds = expectNonEmpty (ai_dmds fun) -- See Invariant of StrictArg;
+ -- ai_dmds is never empty
; (floats1, cont') <- mkDupableContWithDmds env dmds cont
-- Use the demands from the function to add the right
-- demand info on any bindings we make for further args
@@ -4180,7 +4209,10 @@ mkDupableContWithDmds env dmds
-- let a = ...arg...
-- in [...hole...] a
-- NB: sc_dup /= OkToDup; that is caught earlier by contIsDupable
- do { let dmd:|cont_dmds = expectNonEmpty dmds
+ do { let dmd:|cont_dmds =
+ -- We took care to handle an empty demand list at the start,
+ -- ensuring this call to 'expectNonEmpty' does not panic (#27261).
+ expectNonEmpty dmds
; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
; let env' = env `setInScopeFromF` floats1
; arg' <- simplArg env' Nothing hole_ty se arg arg_mco
@@ -4251,7 +4283,7 @@ mkDupableStrictBind env arg_bndr join_rhs res_ty
; let arg_info = ArgInfo { ai_fun = join_bndr
, ai_rules = [], ai_args = []
, ai_encl = False, ai_dmds = repeat topDmd
- , ai_discs = repeat 0 }
+ , ai_discs = Inf.repeat 0 }
; return ( addJoinFloats (emptyFloats env) $
unitJoinFloat $
NonRec join_bndr $
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -25,13 +25,13 @@ module GHC.Core.Opt.Simplify.Utils (
StaticEnv(..),
isSimplified, contIsStop,
contIsDupable, contResultType, contHoleType, contHoleScaling,
- contIsTrivial, contArgs, contIsRhs,
+ contIsTrivial, contArgs, contIsRhs, mkBottomCont,
hasArgs, countArgs, contOutArgs, dropContArgs,
mkBoringStop, mkRhsStop, mkLazyArgStop,
interestingCallContext,
-- ArgInfo
- ArgInfo(..), ArgSpec(..), mkArgInfo,
+ ArgInfo(..), ArgSpec(..), RemainingArgDmds, mkArgInfo,
addValArgTo, addTyArgTo,
argInfoExpr, argSpecArg,
pushOutArgs, pushArgSpecs,
@@ -54,8 +54,10 @@ import GHC.Core.Opt.Stats ( Tick(..) )
import qualified GHC.Core.Subst
import GHC.Core.Ppr
import GHC.Core.TyCo.Ppr ( pprParendType )
+import GHC.Core.TyCo.Compare ( eqTypeIgnoringMultiplicity )
import GHC.Core.FVs
import GHC.Core.Utils
+import GHC.Core.Make( mkWildValBinder )
import GHC.Core.Opt.Arity
import GHC.Core.Unfold
import GHC.Core.Unfold.Make
@@ -75,6 +77,8 @@ import GHC.Types.Var.Set
import GHC.Types.Basic
import GHC.Types.Name.Env
+import GHC.Data.List.Infinite ( Infinite(..) )
+import qualified GHC.Data.List.Infinite as Inf
import GHC.Data.OrdList ( isNilOL )
import GHC.Data.FastString ( fsLit )
@@ -205,10 +209,10 @@ data SimplCont
| StrictArg -- (StrictArg (f e1 ..en) K)[e] = K[ f e1 .. en e ]
{ sc_dup :: DupFlag
- , sc_fun :: ArgInfo -- Specifies f, e1..en, Whether f has rules, etc
+ , sc_fun :: ArgInfo -- Specifies f, e1..en, whether f has rules, etc
-- plus demands and discount flags for *this* arg
-- and further args
- -- So ai_dmds and ai_discs are never empty
+ -- Invariant: ai_dmds and ai_discs are never empty
, sc_fun_ty :: OutType -- Type of the function (f e1 .. en),
-- presumably (arg_ty -> res_ty)
-- where res_ty is expected by sc_cont
@@ -348,32 +352,41 @@ doesn't matter because we'll never compute them all.
data ArgInfo
= ArgInfo {
- ai_fun :: OutId, -- The function
- ai_args :: [ArgSpec], -- ...applied to these args (which are in *reverse* order)
+ ai_fun :: OutId, -- ^ The function
+ ai_args :: [ArgSpec], -- ^ ...applied to these args (which are in *reverse* order)
-- NB: all these argumennts are already simplified
- ai_rules :: [CoreRule], -- Rules for this function
- ai_encl :: Bool, -- Flag saying whether this function
- -- or an enclosing one has rules (recursively)
- -- True => be keener to inline in all args
+ ai_rules :: [CoreRule], -- ^ Rules for this function
+ ai_encl :: Bool,
+ -- ^ Flag saying whether this function or an enclosing one has rules
+ -- (recursively)
+ --
+ -- @True@ means: be keener to inline in all args
- ai_dmds :: [Demand], -- Demands on remaining value arguments (beyond ai_args)
- -- Usually infinite, but if it is finite it guarantees
- -- that the function diverges after being given
- -- that number of args
+ ai_dmds :: RemainingArgDmds,
+ -- ^ Demands on remaining value arguments (beyond 'ai_args')
- ai_discs :: [Int] -- Discounts for remaining value arguments (beyond ai_args)
- -- non-zero => be keener to inline
- -- Always infinite
+ ai_discs :: Infinite Int
+ -- ^ Discounts for remaining value arguments (beyond 'ai_args')
+ --
+ -- A non-zero value means: be keener to inline
}
-data ArgSpec
- = ValArg { as_dmd :: Demand -- Demand placed on this argument
- , as_arg :: OutExpr -- Apply to this (coercion or value); c.f. ApplyToVal
- , as_hole_ty :: OutType } -- Type of the function (presumably t1 -> t2)
+-- | 'RemainingArgDmds' gives the demands on any remaining value arguments.
+--
+-- It is usually infinite (with 'topDmd's in the tail), but if it is finite it
+-- guarantees that the function diverges after being applied to that number
+-- of arguments.
+type RemainingArgDmds = [Demand]
- | TyArg { as_arg_ty :: OutType -- Apply to this type; c.f. ApplyToTy
- , as_hole_ty :: OutType } -- Type of the function (presumably forall a. blah)
+data ArgSpec
+ -- | A value argument
+ = ValArg { as_dmd :: Demand -- ^ Demand placed on this argument
+ , as_arg :: OutExpr -- ^ Apply to this (coercion or value); c.f. 'ApplyToVal'
+ , as_hole_ty :: OutType } -- ^ Type of the function (presumably @t1 -> t2@ for 'ValArg' or @forall a. blah@ for 'TyArg')
+ -- | A type argument
+ | TyArg { as_arg_ty :: OutType -- ^ Apply to this type; c.f. 'ApplyToTy'
+ , as_hole_ty :: OutType } -- ^ Type of the function (presumably @t1 -> t2@ for 'ValArg' or @forall a. blah@ for 'TyArg')
instance Outputable ArgInfo where
ppr (ArgInfo { ai_fun = fun, ai_args = args, ai_dmds = dmds, ai_rules = rules })
@@ -389,7 +402,7 @@ instance Outputable ArgSpec where
addValArgTo :: ArgInfo -> OutExpr -> OutType -> ArgInfo
addValArgTo ai arg hole_ty
- | ArgInfo { ai_dmds = dmd:dmds, ai_discs = _:discs } <- ai
+ | ArgInfo { ai_dmds = dmd:dmds, ai_discs = Inf _ discs } <- ai
-- Pop the top demand and and discounts off
, let arg_spec = ValArg { as_arg = arg, as_hole_ty = hole_ty, as_dmd = dmd }
= ai { ai_args = arg_spec : ai_args ai
@@ -492,12 +505,23 @@ contIsDupable (TickIt _ k) = contIsDupable k
contIsTrivial :: SimplCont -> Bool
contIsTrivial (Stop {}) = True
contIsTrivial (ApplyToTy { sc_cont = k }) = contIsTrivial k
--- This one doesn't look right. A value application is not trivial
--- contIsTrivial (ApplyToVal { sc_arg = Coercion _, sc_cont = k }) = contIsTrivial k
contIsTrivial (CastIt { sc_cont = k }) = contIsTrivial k
contIsTrivial _ = False
-------------------
+contStop :: SimplCont -> SimplCont
+-- ^ Get the 'Stop' at the tail of the continuation
+--
+-- Always returns a continuation of form @(Stop ...)@.
+contStop stop@(Stop {}) = stop
+contStop (CastIt { sc_cont = k }) = contStop k
+contStop (StrictBind { sc_cont = k }) = contStop k
+contStop (StrictArg { sc_cont = k }) = contStop k
+contStop (Select { sc_cont = k }) = contStop k
+contStop (ApplyToTy { sc_cont = k }) = contStop k
+contStop (ApplyToVal { sc_cont = k }) = contStop k
+contStop (TickIt _ k) = contStop k
+
contResultType :: SimplCont -> OutType
contResultType (Stop ty _ _) = ty
contResultType (CastIt { sc_cont = k }) = contResultType k
@@ -651,6 +675,35 @@ contEvalContext bndrs cont = go cont
-- Perhaps reconstruct the demand on the scrutinee by looking at field
-- and case binder dmds, see addCaseBndrDmd. No priority right now.
+-------------------
+mkBottomCont ::SimplCont -> SimplCont
+-- ^ Given a continuation `cont`, return a `cont` /of the same type/,
+-- looking like @(case \<hole\> of {})@.
+--
+-- This is used when we are going to fill in the @<hole>@ with bottom.
+-- See (TC2,3) in Note [Trimming the continuation for bottoming functions]
+--
+-- Don't bother to trim, making a @case <hole> of {}@, if we have only
+-- an essentially-trivial continuation; e.g. @(<hole> \@ty |> co)@.
+mkBottomCont cont = go cont
+ where
+ go k@(Stop {}) = k
+ go (TickIt t k') = TickIt t (go k')
+ go k@(CastIt { sc_cont = k' }) = k { sc_cont = go k' }
+ go k@(ApplyToTy { sc_cont = k' }) = k { sc_cont = go k' }
+ go k@(Select { sc_alts = [], sc_cont = Stop {} }) = k -- Optimisation only
+ go k | Stop res_ty _ _ <- stop_cont
+ , hole_ty `eqTypeIgnoringMultiplicity` res_ty
+ = stop_cont
+ | otherwise
+ = Select { sc_alts = []
+ , sc_bndr = mkWildValBinder OneTy hole_ty
+ , sc_env = Simplified OkDup
+ , sc_cont = stop_cont }
+ where
+ hole_ty = contHoleType k
+ stop_cont = contStop k
+
-------------------
mkArgInfo :: SimplEnv -> Id -> [CoreRule] -> SimplCont -> ArgInfo
mkArgInfo env fun rules_for_fun cont
@@ -672,16 +725,17 @@ mkArgInfo env fun rules_for_fun cont
fun_has_rules = not (null rules_for_fun)
- vanilla_discounts, arg_discounts :: [Int]
- vanilla_discounts = repeat 0
+ vanilla_discounts, arg_discounts :: Infinite Int
+ vanilla_discounts = Inf.repeat 0
arg_discounts = case idUnfolding fun of
CoreUnfolding {uf_guidance = UnfIfGoodArgs {ug_args = discounts}}
- -> discounts ++ vanilla_discounts
+ -> discounts Inf.++ vanilla_discounts
_ -> vanilla_discounts
- vanilla_dmds, arg_dmds :: [Demand]
+ vanilla_dmds :: RemainingArgDmds
vanilla_dmds = repeat topDmd
+ arg_dmds :: RemainingArgDmds
arg_dmds
| not (seInline env)
= vanilla_dmds -- See Note [Do not expose strictness if sm_inline=False]
@@ -689,26 +743,22 @@ mkArgInfo env fun rules_for_fun cont
= -- add_type_str fun_ty $
case splitDmdSig (idDmdSig fun) of
(demands, result_info)
- | not (demands `lengthExceeds` n_val_args)
- -> -- Enough args, use the strictness given.
- -- For bottoming functions we used to pretend that the arg
- -- is lazy, so that we don't treat the arg as an
- -- interesting context. This avoids substituting
- -- top-level bindings for (say) strings into
- -- calls to error. But now we are more careful about
- -- inlining lone variables, so its ok
- -- (see GHC.Core.Op.Simplify.Utils.analyseCont)
- if isDeadEndDiv result_info then
- demands -- Finite => result is bottom
- else
- demands ++ vanilla_dmds
+ | not (demands `lengthExceeds` n_val_args)
+ -> remaining_dmds -- Enough args, use the strictness given.
| otherwise
-> warnPprTrace True "More demands than arity" (ppr fun <+> ppr (idArity fun)
<+> ppr n_val_args <+> ppr demands) $
vanilla_dmds -- Not enough args, or no strictness
- add_type_strictness :: Type -> [Demand] -> [Demand]
- -- If the function arg types are strict, record that in the 'strictness bits'
+ where
+ remaining_dmds :: RemainingArgDmds
+ -- isDeadEndDiv: if remaining_dmds is finite, result is bottom
+ -- See (TC1) in Note [Trimming the continuation for bottoming functions]
+ remaining_dmds | isDeadEndDiv result_info = demands
+ | otherwise = demands ++ vanilla_dmds
+
+ add_type_strictness :: Type -> RemainingArgDmds -> RemainingArgDmds
+ -- If the function arg /types/ are strict, record that in the RemainingArgDmds
-- No need to instantiate because unboxed types (which dominate the strict
-- types) can't instantiate type variables.
-- add_type_strictness is done repeatedly (for each call);
@@ -915,16 +965,16 @@ the incentive to disappear when we inline `f`!
lazyArgContext :: ArgInfo -> CallCtxt
-- Use this for lazy arguments
lazyArgContext (ArgInfo { ai_encl = encl_rules, ai_discs = discs })
- | encl_rules = RuleArgCtxt
- | disc:_ <- discs, disc > 0 = DiscArgCtxt -- Be keener here
- | otherwise = BoringCtxt -- Nothing interesting
+ | encl_rules = RuleArgCtxt
+ | Inf disc _ <- discs, disc > 0 = DiscArgCtxt -- Be keener here
+ | otherwise = BoringCtxt -- Nothing interesting
strictArgContext :: ArgInfo -> CallCtxt
strictArgContext (ArgInfo { ai_encl = encl_rules, ai_discs = discs })
-- Use this for strict arguments
- | encl_rules = RuleArgCtxt
- | disc:_ <- discs, disc > 0 = DiscArgCtxt -- Be keener here
- | otherwise = RhsCtxt NonRecursive
+ | encl_rules = RuleArgCtxt
+ | Inf disc _ <- discs, disc > 0 = DiscArgCtxt -- Be keener here
+ | otherwise = RhsCtxt NonRecursive
-- Why RhsCtxt? if we see f (g x), and f is strict, we
-- want to be a bit more eager to inline g, because it may
-- expose an eval (on x perhaps) that can be eliminated or
=====================================
hadrian/src/Rules/BinaryDist.hs
=====================================
@@ -331,7 +331,22 @@ bindistRules = do
ghcRoot <- topDirectory
copyFile (ghcRoot -/- "aclocal.m4") (ghcRoot -/- "distrib" -/- "aclocal.m4")
copyDirectory (ghcRoot -/- "m4") (ghcRoot -/- "distrib")
- buildWithCmdOptions [] $
+
+ -- Get the normalized ACLOCAL_PATH for Windows
+ -- This is necessary since on Windows this will be a Windows
+ -- path, which autoreconf doesn't know how to handle.
+ --
+ -- This logic is duplicated in the `boot` python script
+ win_host <- isWinHost
+ env <- if not win_host
+ then pure []
+ else do
+ aclocalPathMay <- getEnv "ACLOCAL_PATH"
+ pure [ AddEnv "ACLOCAL_PATH" (msys2WindowsToUnixPath aclocalPath)
+ | Just aclocalPath <- [aclocalPathMay]
+ ]
+
+ buildWithCmdOptions env $
target (vanillaContext Stage1 ghc) (Autoreconf $ ghcRoot -/- "distrib") [] []
-- We clean after ourselves, moving the configure script we generated in
-- our bindist dir
=====================================
hadrian/src/Utilities.hs
=====================================
@@ -3,7 +3,8 @@ module Utilities (
askWithResources,
runBuilder, runBuilderWith,
contextDependencies, stage1Dependencies,
- topsortPackages, cabalDependencies
+ topsortPackages, cabalDependencies,
+ msys2WindowsToUnixPath
) where
import qualified Hadrian.Builder as H
@@ -69,3 +70,17 @@ topsortPackages pkgs = do
let annotated = map (annotateInDeg es) es
inDegZero = map snd $ filter ((== 0). fst) annotated
in inDegZero ++ topSort (es \\ inDegZero)
+
+-- | Converts a windows style path to a unix style path using msys2 conventions.
+-- >>> msys2WindowsToUnixPath "C:\\foo\\bar;C:\\msys2\\bin"
+-- "/C/foo/bar:/c/msys2/bin"
+msys2WindowsToUnixPath :: String -> String
+msys2WindowsToUnixPath =
+ replaceDrivePrefix
+ . replace "\\" "/"
+ . replace ";" ":"
+ where
+ replaceDrivePrefix p = case p of
+ drive : ':' : '/' : rest -> '/' : drive : '/' : replaceDrivePrefix rest
+ c : cs -> c : replaceDrivePrefix cs
+ [] -> []
=====================================
libraries/ghc-boot/GHC/Data/ShortByteString.hs
=====================================
@@ -0,0 +1,17 @@
+module GHC.Data.ShortByteString
+ ( newCStringFromSBS
+ ) where
+
+import Prelude
+
+import qualified Data.ByteString.Short as SBS
+import Foreign
+import Foreign.C
+
+newCStringFromSBS :: SBS.ShortByteString -> IO CString
+newCStringFromSBS sbs =
+ SBS.useAsCStringLen sbs $ \(src, len) -> do
+ dst <- mallocBytes (len + 1)
+ copyBytes dst src len
+ pokeByteOff dst len (0 :: Word8)
+ pure dst
=====================================
libraries/ghc-boot/ghc-boot.cabal.in
=====================================
@@ -51,6 +51,7 @@ Library
exposed-modules:
GHC.BaseDir
+ GHC.Data.ShortByteString
GHC.Data.ShortText
GHC.Data.SizedSeq
GHC.Data.SmallArray
=====================================
libraries/ghci/GHCi/Coverage.hs
=====================================
@@ -9,9 +9,9 @@ import Prelude -- See note [Why do we import Prelude here?]
import Control.Exception
import Data.ByteString.Short (ShortByteString)
-import qualified Data.ByteString.Short as SBS
import Data.Word
import Foreign
+import GHC.Data.ShortByteString
import GHC.Foreign (CString)
import GHC.Utils.Encoding.UTF8 (utf8DecodeShortByteString)
import GHCi.ObjLink (lookupSymbol)
@@ -31,17 +31,19 @@ hpcAddModule ::
-- ^ Name of the ticks array found in the c-stub.
IO ()
hpcAddModule modlName ticks hash tickboxes = do
- SBS.useAsCString modlName $ \modlNameLiteral -> do
- -- we need to find the reference to the ticks array.
- lookupSymbol tickboxes >>= \ case
- Nothing -> do
- -- the symbol is not found, this is a bug!
- throwIO $ ErrorCall $ "hpcAddModule: failed to find symbol " <> utf8DecodeShortByteString tickboxes
- Just tickBoxRef -> do
- -- Calling 'hs_hpc_module' multiple times is safe, it will add the module only once.
- hpc_register_module modlNameLiteral (fromIntegral ticks) (fromIntegral hash) (castPtr tickBoxRef)
- -- calling 'hpc_startup' multiple times is safe, it will only be initialised once.
- hpc_startup
+ -- we need to find the reference to the ticks array.
+ lookupSymbol tickboxes >>= \ case
+ Nothing -> do
+ -- the symbol is not found, this is a bug!
+ throwIO $ ErrorCall $ "hpcAddModule: failed to find symbol " <> utf8DecodeShortByteString tickboxes
+ Just tickBoxRef -> do
+ -- hs_hpc_module stores the module name pointer in the RTS hash table
+ -- until exitHpc, so pass a malloced C string.
+ modlNameLiteral <- newCStringFromSBS modlName
+ -- Calling 'hs_hpc_module' multiple times is safe, it will add the module only once.
+ hpc_register_module modlNameLiteral (fromIntegral ticks) (fromIntegral hash) (castPtr tickBoxRef)
+ -- calling 'hpc_startup' multiple times is safe, it will only be initialised once.
+ hpc_startup
foreign import ccall unsafe "hs_hpc_module"
hpc_register_module :: CString -> Word32 -> Word32 -> Ptr Word64 -> IO ()
=====================================
libraries/ghci/GHCi/Run.hs
=====================================
@@ -37,6 +37,9 @@ import Control.Monad
import Data.ByteString (ByteString)
import qualified Data.ByteString.Short.Internal as BS
import qualified Data.ByteString.Unsafe as B
+#if defined(PROFILING)
+import GHC.Data.ShortByteString
+#endif
import GHC.Exts
import qualified GHC.Exts.Heap as Heap
import GHC.Stack
@@ -447,13 +450,6 @@ mkCostCentres mod ccs = do
c_srcspan <- newCStringFromSBS srcspan
toRemotePtr <$> c_mkCostCentre c_name c_module c_srcspan
- newCStringFromSBS sbs = do
- let len = BS.length sbs
- buf <- mallocBytes $ len + 1
- BS.copyToPtr sbs 0 buf (fromIntegral len)
- pokeByteOff buf len (0 :: Word8)
- pure buf
-
foreign import ccall unsafe "mkCostCentre"
c_mkCostCentre :: Ptr CChar -> Ptr CChar -> Ptr CChar -> IO (Ptr CostCentre)
#else
=====================================
testsuite/tests/perf/compiler/all.T
=====================================
@@ -678,7 +678,7 @@ test ('T18140',
['-v0 -O'])
test('T10421',
[ only_ways(['normal']),
- collect_compiler_runtime(1)
+ collect_compiler_runtime(2) # 1% tolerance was too small (#27289)
],
multimod_compile,
['T10421', '-v0 -O'])
=====================================
testsuite/tests/simplCore/should_compile/T27261.hs
=====================================
@@ -0,0 +1,17 @@
+{-# OPTIONS_GHC -fno-full-laziness #-}
+
+module T27261 (foo) where
+
+import T27261_aux (myError)
+
+foo :: [String] -> (() -> Int) -> Int
+foo cs =
+ \ k -> ( case bar of
+ Just str -> let cs2 = case cs of { [] -> cs; _ -> "stack entry" : cs }
+ in myError cs2 str
+ Nothing -> \ c -> c () )
+ ( \ _ -> k () )
+
+bar :: Maybe String
+bar = Nothing
+{-# NOINLINE bar #-}
=====================================
testsuite/tests/simplCore/should_compile/T27261_aux.hs
=====================================
@@ -0,0 +1,7 @@
+{-# LANGUAGE BangPatterns #-}
+
+module T27261_aux (myError) where
+
+myError :: [String] -> String -> a
+myError !_ _ = undefined
+{-# NOINLINE myError #-}
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -601,3 +601,4 @@ test('T25718a', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress
test('T25718b', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-all -dno-typeable-binds'])
test('T25718c', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-all -dno-typeable-binds'])
test('T19166', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-all -dno-typeable-binds'])
+test('T27261', [extra_files(['T27261_aux.hs'])], multimod_compile, ['T27261', '-v0 -O'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2b6f845ab0a42877a0c0e9a11f5ac5…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2b6f845ab0a42877a0c0e9a11f5ac5…
You're receiving this email because of your account on gitlab.haskell.org.
1
0