[Git][ghc/ghc][master] JS: fix recompilation avoidance (#23013)
by Marge Bot (@marge-bot) 13 Mar '26
by Marge Bot (@marge-bot) 13 Mar '26
13 Mar '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
a13245a9 by Sylvain Henry at 2026-03-13T15:10:06-04:00
JS: fix recompilation avoidance (#23013)
- we were checking the mtime of the *.jsexe directory, not of a file
- we were not computing the PkgsLoaded at all
- - - - -
14 changed files:
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Linker/Loader.hs
- testsuite/tests/annotations/should_run/all.T
- − testsuite/tests/driver/OneShotTH.stdout-javascript-unknown-ghcjs
- + testsuite/tests/driver/T20604/T20604.stdout-javascript-unknown-ghcjs
- testsuite/tests/driver/T20604/all.T
- testsuite/tests/driver/all.T
- testsuite/tests/driver/fat-iface/fat010.stdout-javascript-unknown-ghcjs
- testsuite/tests/driver/recomp011/all.T
- testsuite/tests/driver/recompHash/recompHash.stdout-javascript-unknown-ghcjs
- testsuite/tests/driver/recompNoTH/recompNoTH.stdout-javascript-unknown-ghcjs
- − testsuite/tests/driver/th-new-test/th-new-test.stdout-javascript-unknown-ghcjs
Changes:
=====================================
compiler/GHC/Driver/Main.hs
=====================================
@@ -106,8 +106,6 @@ module GHC.Driver.Main
import GHC.Prelude
-import GHC.Platform
-
import GHC.Driver.Plugins
import GHC.Driver.Session
import GHC.Driver.Backend
@@ -259,8 +257,6 @@ import GHC.Utils.Logger
import GHC.Utils.TmpFs
import GHC.Utils.Touch
-import qualified GHC.LanguageExtensions as LangExt
-
import GHC.Data.FastString
import GHC.Data.Bag
import GHC.Data.OsPath (unsafeEncodeUtf)
@@ -295,8 +291,8 @@ import System.IO.Unsafe ( unsafeInterleaveIO )
import GHC.Iface.Env ( trace_if )
import GHC.Stg.EnforceEpt.TagSig (seqTagSig)
import GHC.StgToCmm.Utils (IPEStats)
+import GHC.Types.Unique.DSet ( uniqDSetToList )
import GHC.Types.Unique.FM
-import GHC.Types.Unique.DFM
import GHC.Cmm.Config (CmmConfig)
import Data.Bifunctor
import qualified GHC.Unit.Home.Graph as HUG
@@ -855,14 +851,6 @@ hscRecompStatus
msg UpToDate
return $ HscUpToDate checked_iface emptyRecompLinkables
- -- Always recompile with the JS backend when TH is enabled until
- -- #23013 is fixed.
- | ArchJavaScript <- platformArch (targetPlatform lcl_dflags)
- , xopt LangExt.TemplateHaskell lcl_dflags
- -> do
- msg $ needsRecompileBecause THWithJS
- return $ HscRecompNeeded $ Just $ mi_iface_hash $ checked_iface
-
| otherwise -> do
-- Check the status of all the linkable types we might need.
-- 1. The in-memory linkable we had at hand.
@@ -2910,7 +2898,7 @@ jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do
initLoaderState interp hsc_env
-- Take lock for the actual work.
- (dep_linkables, needed_units) <- modifyLoaderState interp $ \pls -> do
+ (dep_linkables, needed_units, this_pkgs_loaded) <- modifyLoaderState interp $ \pls -> do
let link_opts = initLinkDepsOpts hsc_env
-- Find what packages and linkables are required
@@ -2921,11 +2909,14 @@ jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do
let objs = mapMaybe linkableFilterNative (ldNeededLinkables deps)
(objs_loaded', _new_objs) = rmDupLinkables (objs_loaded pls) objs
- -- FIXME: we should make the JS linker load new_objs here, instead of
- -- on-demand.
-
- let pls' = pls { objs_loaded = objs_loaded' }
- pure (pls', (ldAllLinkables deps, ldUnits deps))
+ -- Compute LoadedPkgInfo metadata for recompilation avoidance.
+ -- We don't call loadPackages' because the JS interpreter doesn't load
+ -- native .o/.so files; we only need the transitive-dep metadata.
+ (_, pkgs_almost_loaded) <-
+ loadMoreUnits hsc_env (ldUnits deps) (pkgs_loaded pls)
+ let this_pkgs_loaded = filterNeededPkgsLoaded (ldNeededUnits deps) pkgs_almost_loaded
+ pls' = pls { objs_loaded = objs_loaded', pkgs_loaded = pkgs_almost_loaded }
+ pure (pls', (ldAllLinkables deps, uniqDSetToList (ldNeededUnits deps), this_pkgs_loaded))
let foreign_stubs = NoStubs
@@ -2950,11 +2941,7 @@ jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do
binding_fref <- withJSInterp i $ \inst ->
mkForeignRef href (freeReallyRemoteRef inst href)
- -- FIXME: we don't report needed units because we would have to find a way to
- -- build a meaningful LoadedPkgInfo (see the mess in
- -- GHC.Linker.Loader.{loadPackage,loadPackages'}).
- let pkgs_loaded = emptyUDFM
- return (castForeignRef binding_fref, dep_linkables, pkgs_loaded)
+ return (castForeignRef binding_fref, dep_linkables, this_pkgs_loaded)
{- **********************************************************************
=====================================
compiler/GHC/Driver/Pipeline.hs
=====================================
@@ -556,7 +556,14 @@ checkNativeLibraryLinkingNeeded staticLink _ dflags unit_env linkables pkg_deps
unit_state = ue_homeUnitState unit_env
arch_os = platformArchOS platform
exe_file = exeFileName arch_os staticLink (outputFile_ dflags)
- exe_file_os <- SysOsPath.encodeFS exe_file
+ -- For the JS backend, exe_file is a directory (*.jsexe). A directory's
+ -- mtime on Linux is only updated when entries are created/deleted, not
+ -- when existing files are overwritten. jsLink always overwrites out.js,
+ -- so use that as the mtime sentinel instead.
+ exe_time_file
+ | ArchJavaScript <- platformArch platform = exe_file </> "out.js"
+ | otherwise = exe_file
+ exe_file_os <- SysOsPath.encodeFS exe_time_file
e_exe_time <- modificationTimeIfExists exe_file_os
case e_exe_time of
Nothing -> return $ NeedsRecompile MustCompile
=====================================
compiler/GHC/Iface/Recomp.hs
=====================================
@@ -204,7 +204,6 @@ data RecompReason
| MismatchedDynHiFile
| ObjectsChanged
| LibraryChanged
- | THWithJS
deriving (Eq)
@@ -241,7 +240,6 @@ instance Outputable RecompReason where
MismatchedDynHiFile -> text "Mismatched dynamic interface file"
ObjectsChanged -> text "Objects changed"
LibraryChanged -> text "Library changed"
- THWithJS -> text "JS backend always recompiles modules using Template Haskell for now (#23013)"
recompileRequired :: RecompileRequired -> Bool
recompileRequired UpToDate = False
=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -36,6 +36,8 @@ module GHC.Linker.Loader
, initLinkDepsOpts
, getGccSearchDirectory
, mkDynLoadLib
+ , loadMoreUnits
+ , filterNeededPkgsLoaded
)
where
@@ -252,6 +254,20 @@ loadName interp hsc_env name = do
(ppr sym_to_find)
return (pls,(r, links, pkgs))
+-- | Restrict a 'PkgsLoaded' map to the packages directly needed and their
+-- full transitive closure (via 'loaded_pkg_trans_deps').
+filterNeededPkgsLoaded :: UniqDSet UnitId -> PkgsLoaded -> PkgsLoaded
+filterNeededPkgsLoaded directly_needed all_pkgs_loaded =
+ udfmRestrictKeys all_pkgs_loaded $ getUniqDSet trans_pkgs_needed
+ where
+ trans_pkgs_needed =
+ unionManyUniqDSets
+ (directly_needed :
+ [ loaded_pkg_trans_deps pkg
+ | pkg_id <- uniqDSetToList directly_needed
+ , Just pkg <- [lookupUDFM all_pkgs_loaded pkg_id]
+ ])
+
loadDependencies
:: Interp
-> HscEnv
@@ -271,12 +287,7 @@ loadDependencies interp hsc_env pls span needed_mods = do
-- Link the packages and modules required
pls1 <- loadPackages' interp hsc_env (ldUnits deps) pls
(pls2, succ) <- loadExternalModuleLinkables interp hsc_env pls1 (ldNeededLinkables deps)
- let this_pkgs_loaded = udfmRestrictKeys all_pkgs_loaded $ getUniqDSet trans_pkgs_needed
- all_pkgs_loaded = pkgs_loaded pls2
- trans_pkgs_needed = unionManyUniqDSets (this_pkgs_needed : [ loaded_pkg_trans_deps pkg
- | pkg_id <- uniqDSetToList this_pkgs_needed
- , Just pkg <- [lookupUDFM all_pkgs_loaded pkg_id]
- ])
+ let this_pkgs_loaded = filterNeededPkgsLoaded this_pkgs_needed (pkgs_loaded pls2)
return (pls2, succ, ldAllLinkables deps, this_pkgs_loaded)
@@ -1170,17 +1181,26 @@ loadPackages interp hsc_env new_pkgs = do
modifyLoaderState_ interp $ \pls ->
loadPackages' interp hsc_env new_pkgs pls
-loadPackages' :: Interp -> HscEnv -> [UnitId] -> LoaderState -> IO LoaderState
-loadPackages' interp hsc_env new_pks pls = do
- (reverse -> pkgs_info_list, pkgs_almost_loaded) <-
- downsweep
- ([], pkgs_loaded pls)
- new_pks
- loadPackage interp hsc_env pkgs_info_list (pls { pkgs_loaded = pkgs_almost_loaded })
+-- | Compute 'LoadedPkgInfo' metadata (with transitive deps) for new packages,
+-- without loading any native libraries. Used for recompilation-avoidance
+-- tracking and as the first pass of 'loadPackages''.
+--
+-- The returned '[UnitInfo]' list is an accumulated *reverse* topologically
+-- sorted list of new packages. The returned 'PkgsLoaded' is populated with
+-- placeholder 'LoadedPkgInfo' for new packages (empty artifact fields, correct
+-- 'loaded_pkg_trans_deps').
+loadMoreUnits
+ :: HscEnv
+ -> [UnitId] -- ^ New packages to process (not yet in PkgsLoaded)
+ -> PkgsLoaded -- ^ Existing loaded packages (used for memoization)
+ -> IO ([UnitInfo], PkgsLoaded)
+ -- ^ Reverse topologically-sorted new package infos + updated PkgsLoaded
+loadMoreUnits hsc_env new_pks pkgs_loaded_init =
+ downsweep ([], pkgs_loaded_init) new_pks
where
-- The downsweep process takes an initial 'PkgsLoaded' and uses it
-- to memoize new packages to load when recursively downsweeping
- -- the dependencies. The returned 'PkgsLoaded' is popularized with
+ -- the dependencies. The returned 'PkgsLoaded' is populated with
-- placeholder 'LoadedPkgInfo' for new packages yet to be loaded,
-- which need to be modified later to fill in the missing fields.
--
@@ -1221,6 +1241,12 @@ loadPackages' interp hsc_env new_pks pls = do
throwGhcExceptionIO
(CmdLineError ("unknown package: " ++ unpackFS (unitIdFS new_pkg)))
+loadPackages' :: Interp -> HscEnv -> [UnitId] -> LoaderState -> IO LoaderState
+loadPackages' interp hsc_env new_pks pls = do
+ (reverse -> pkgs_info_list, pkgs_almost_loaded) <-
+ loadMoreUnits hsc_env new_pks (pkgs_loaded pls)
+ loadPackage interp hsc_env pkgs_info_list (pls { pkgs_loaded = pkgs_almost_loaded })
+
loadPackage :: Interp -> HscEnv -> [UnitInfo] -> LoaderState -> IO LoaderState
loadPackage interp hsc_env pkgs pls
=====================================
testsuite/tests/annotations/should_run/all.T
=====================================
@@ -10,9 +10,6 @@ test('annrun01',
[extra_files(['Annrun01_Help.hs']),
req_th,
req_process,
- js_broken(23013), # strangely, the workaround for #23013 triggers
- # a call to an undefined FFI function in bytestring.
- # Before, it was slow but not failing.
when(js_arch(), compile_timeout_multiplier(5)),
pre_cmd('$MAKE -s --no-print-directory config'),
omit_ways(['dyn'] + prof_ways)],
=====================================
testsuite/tests/driver/OneShotTH.stdout-javascript-unknown-ghcjs deleted
=====================================
=====================================
testsuite/tests/driver/T20604/T20604.stdout-javascript-unknown-ghcjs
=====================================
@@ -0,0 +1,2 @@
+A1
+A
=====================================
testsuite/tests/driver/T20604/all.T
=====================================
@@ -10,6 +10,5 @@ def normalise_paths(s):
test('T20604', [ req_th
- , js_broken(23013)
, extra_files(['A.hs', 'A1.hs'])
, normalise_fun(normalise_paths)], makefile_test, [])
=====================================
testsuite/tests/driver/all.T
=====================================
@@ -299,7 +299,7 @@ test('T18369', normal, compile, ['-O'])
test('T21682', normal, compile_fail, ['-Werror=unrecognised-warning-flags -Wfoo'])
test('FullGHCVersion', normal, compile_and_run, ['-package ghc-boot'])
test('OneShotTH', req_th, makefile_test, [])
-test('T17481', js_broken(23013), makefile_test, [])
+test('T17481', normal, makefile_test, [])
test('T20084', normal, makefile_test, [])
test('RunMode', [req_interp,extra_files(['RunMode/Test.hs'])], run_command, ['{compiler} --run -iRunMode/ -ignore-dot-ghci RunMode.hs -- hello'])
test('T20439', normal, run_command,
=====================================
testsuite/tests/driver/fat-iface/fat010.stdout-javascript-unknown-ghcjs
=====================================
@@ -1,5 +1,4 @@
[1 of 3] Compiling THA
[2 of 3] Compiling THB
[3 of 3] Compiling THC
-[1 of 3] Compiling THA [JS backend always recompiles modules using Template Haskell for now (#23013)]
[2 of 3] Compiling THB [Source file changed]
=====================================
testsuite/tests/driver/recomp011/all.T
=====================================
@@ -2,6 +2,5 @@
test('recomp011',
[ extra_files(['Main.hs'])
- , js_broken(23013)
],
makefile_test, [])
=====================================
testsuite/tests/driver/recompHash/recompHash.stdout-javascript-unknown-ghcjs
=====================================
@@ -1,3 +1,2 @@
[1 of 2] Compiling B
[2 of 2] Compiling A
-[2 of 2] Compiling A [JS backend always recompiles modules using Template Haskell for now (#23013)]
=====================================
testsuite/tests/driver/recompNoTH/recompNoTH.stdout-javascript-unknown-ghcjs
=====================================
@@ -1,4 +1,3 @@
[1 of 2] Compiling B
[2 of 2] Compiling A
[1 of 2] Compiling B [Source file changed]
-[2 of 2] Compiling A [JS backend always recompiles modules using Template Haskell for now (#23013)]
=====================================
testsuite/tests/driver/th-new-test/th-new-test.stdout-javascript-unknown-ghcjs deleted
=====================================
@@ -1,26 +0,0 @@
-[1 of 6] Compiling B
-[2 of 6] Compiling A
-[3 of 6] Compiling D
-[4 of 6] Compiling C
-[5 of 6] Compiling Main
-[6 of 6] Linking Main
-[1 of 6] Compiling B [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[2 of 6] Compiling A [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[3 of 6] Compiling D [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[4 of 6] Compiling C [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[6 of 6] Linking Main [Objects changed]
-[1 of 6] Compiling B [Source file changed]
-[2 of 6] Compiling A [B[TH] changed]
-[3 of 6] Compiling D [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[4 of 6] Compiling C [D[TH] changed]
-[6 of 6] Linking Main [Objects changed]
-[1 of 6] Compiling B [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[2 of 6] Compiling A [JS backend always recompiles modules using Template Haskell for now (#23013)]
-[3 of 6] Compiling D [Source file changed]
-[4 of 6] Compiling C [D[TH] changed]
-[6 of 6] Linking Main [Objects changed]
-[1 of 6] Compiling B [Source file changed]
-[2 of 6] Compiling A [B[TH] changed]
-[3 of 6] Compiling D [Source file changed]
-[4 of 6] Compiling C [D[TH] changed]
-[6 of 6] Linking Main [Objects changed]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a13245a92c4cacf81b7adf41cc36022…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a13245a92c4cacf81b7adf41cc36022…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
13 Mar '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
905f8723 by Simon Jakobi at 2026-03-13T15:09:09-04:00
Add regression test for #2057
Test that GHC stops after an interface-file error instead of
continuing into the linker.
The test constructs a stale package dependency on purpose. `pkgB` is compiled
against one version of package `A`, then the same unit id is replaced by an
incompatible build of `A`. When `Main` imports `B`, GHC has to read `B.hi`,
finds an unfolding that still mentions the old `A`, and should fail while
loading interfaces.
Closes #2057.
Assisted-by: Codex
- - - - -
12 changed files:
- testsuite/.gitignore
- + testsuite/tests/driver/T2057/Makefile
- + testsuite/tests/driver/T2057/README.md
- + testsuite/tests/driver/T2057/T2057.stderr
- + testsuite/tests/driver/T2057/all.T
- + testsuite/tests/driver/T2057/app/Main.hs
- + testsuite/tests/driver/T2057/pkgA1/A.hs
- + testsuite/tests/driver/T2057/pkgA1/pkg.conf
- + testsuite/tests/driver/T2057/pkgA2/A.hs
- + testsuite/tests/driver/T2057/pkgA2/pkg.conf
- + testsuite/tests/driver/T2057/pkgB/B.hs
- + testsuite/tests/driver/T2057/pkgB/pkg.conf
Changes:
=====================================
testsuite/.gitignore
=====================================
@@ -551,6 +551,7 @@ mk/ghcconfig*_test___spaces_ghc*.exe.mk
/tests/driver/T10970
/tests/driver/T1959/E.hs
/tests/driver/T1959/prog
+/tests/driver/T2057/work/
/tests/driver/T3007/A/Setup
/tests/driver/T3007/A/dist/
/tests/driver/T3007/B/Setup
=====================================
testsuite/tests/driver/T2057/Makefile
=====================================
@@ -0,0 +1,52 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+WORK = work
+PKGDB = $(WORK)/pkgdb
+PKGA1 = $(WORK)/pkgA1
+PKGA2 = $(WORK)/pkgA2
+PKGB = $(WORK)/pkgB
+APP = $(WORK)/app
+OUT = $(WORK)/T2057.out
+
+.PHONY: T2057 clean
+
+clean:
+ rm -rf $(WORK)
+
+T2057: clean
+
+ # Create an isolated package DB and output directories for the repro.
+ mkdir -p '$(PKGA1)' '$(PKGA2)' '$(PKGB)' '$(APP)'
+ '$(GHC_PKG)' init '$(PKGDB)'
+
+ # Build and register pkgA from the pkgA1 sources.
+ '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' \
+ -this-unit-id pkgA -O -c pkgA1/A.hs -outputdir '$(PKGA1)'
+ '$(AR)' q '$(PKGA1)/libHSpkgA.a' '$(PKGA1)/A.o' >/dev/null 2>&1
+ cp pkgA1/pkg.conf '$(WORK)/pkgA1.conf'
+ '$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgA1.conf' >/dev/null
+
+ # Build and register pkgB against pkgA so INLINE g records the unfolding g = f in B.hi.
+ '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' \
+ -package pkgA -this-unit-id pkgB -O -c pkgB/B.hs \
+ -outputdir '$(PKGB)'
+ '$(AR)' q '$(PKGB)/libHSpkgB.a' '$(PKGB)/B.o' >/dev/null 2>&1
+ cp pkgB/pkg.conf '$(WORK)/pkgB.conf'
+ '$(GHC_PKG)' --package-db '$(PKGDB)' register '$(WORK)/pkgB.conf' >/dev/null
+
+ # Rebuild pkgA from the pkgA2 source tree, removing f.
+ '$(TEST_HC)' $(TEST_HC_OPTS) -v0 -package-db '$(PKGDB)' \
+ -this-unit-id pkgA -O -c pkgA2/A.hs -outputdir '$(PKGA2)'
+ '$(AR)' q '$(PKGA2)/libHSpkgA.a' '$(PKGA2)/A.o' >/dev/null 2>&1
+ cp pkgA2/pkg.conf '$(WORK)/pkgA2.conf'
+ '$(GHC_PKG)' --package-db '$(PKGDB)' update '$(WORK)/pkgA2.conf' >/dev/null
+
+ # Compiling Main against pkgB should now fail while loading the stale B.hi.
+ ! '$(TEST_HC)' $(TEST_HC_OPTS) -v0 --make app/Main.hs \
+ -O -fforce-recomp -package-db '$(PKGDB)' -package pkgB \
+ >'$(OUT)' 2>&1 || { echo "expected compilation failure" >&2; exit 1; }
+
+ # Strip the absolute test directory prefix before comparing against T2057.stderr.
+ sed "s#$(CURDIR)/##g" '$(OUT)' >&2
=====================================
testsuite/tests/driver/T2057/README.md
=====================================
@@ -0,0 +1,23 @@
+`T2057` checks that GHC stops after an interface-file error instead of
+continuing into the linker.
+
+The test constructs a stale package dependency on purpose.
+
+The dependency tree is
+
+ app/Main -> pkgB -> pkgA
+
+where the two directories `pkgA1/` and `pkgA2/` are just two source trees
+for the same package `pkgA`.
+
+`pkgA1` defines a local type `T` and a function `f :: T -> T`.
+`pkgB` builds against that package and records an unfolding `g = f` in `B.hi`.
+
+After that, the Makefile updates the same package `pkgA` from `pkgA2/`, where
+module `A` no longer exports `f`. When `Main` imports `B`, GHC has to load
+`B.hi`, sees the stale reference to `f`, and must fail.
+
+The golden [`T2057.stderr`](T2057.stderr) captures the fixed behaviour:
+diagnose the missing declaration in the stale interface and then stop with
+`Cannot continue after interface file error`. Any linker output would be a
+regression.
=====================================
testsuite/tests/driver/T2057/T2057.stderr
=====================================
@@ -0,0 +1,9 @@
+work/pkgB/B.hi
+Declaration for g
+Unfolding of g:
+ f ErrorWithoutFlag
+ Can't find interface-file declaration for variable f
+ Probable cause: bug in .hi-boot file, or inconsistent .hi file
+ Use -ddump-if-trace to get an idea of which file caused the error
+<no location info>:
+ Cannot continue after interface file error
=====================================
testsuite/tests/driver/T2057/all.T
=====================================
@@ -0,0 +1,8 @@
+test(
+ 'T2057',
+ [ extra_files(['pkgA1', 'pkgA2', 'pkgB', 'app', 'README.md'])
+ , ignore_stdout
+ ],
+ makefile_test,
+ []
+)
=====================================
testsuite/tests/driver/T2057/app/Main.hs
=====================================
@@ -0,0 +1,7 @@
+module Main where
+
+import B
+
+main :: IO ()
+main = case g MkT of
+ MkT -> print ()
=====================================
testsuite/tests/driver/T2057/pkgA1/A.hs
=====================================
@@ -0,0 +1,7 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module A (T(..), f) where
+
+data T = MkT
+
+f :: T -> T
+f x = x
=====================================
testsuite/tests/driver/T2057/pkgA1/pkg.conf
=====================================
@@ -0,0 +1,11 @@
+name: pkgA
+version: 1.0
+id: pkgA
+key: pkgA
+exposed: True
+exposed-modules: A
+import-dirs: ${pkgroot}/pkgA1
+library-dirs: ${pkgroot}/pkgA1
+dynamic-library-dirs: ${pkgroot}/pkgA1
+hs-libraries: HSpkgA
+depends:
=====================================
testsuite/tests/driver/T2057/pkgA2/A.hs
=====================================
@@ -0,0 +1,5 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module A where
+
+-- no f here
+data T = MkT
=====================================
testsuite/tests/driver/T2057/pkgA2/pkg.conf
=====================================
@@ -0,0 +1,11 @@
+name: pkgA
+version: 1.0
+id: pkgA
+key: pkgA
+exposed: True
+exposed-modules: A
+import-dirs: ${pkgroot}/pkgA2
+library-dirs: ${pkgroot}/pkgA2
+dynamic-library-dirs: ${pkgroot}/pkgA2
+hs-libraries: HSpkgA
+depends:
=====================================
testsuite/tests/driver/T2057/pkgB/B.hs
=====================================
@@ -0,0 +1,8 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module B (T(..), g) where
+
+import A
+
+{-# INLINE g #-}
+g :: T -> T
+g x = f x
=====================================
testsuite/tests/driver/T2057/pkgB/pkg.conf
=====================================
@@ -0,0 +1,11 @@
+name: pkgB
+version: 1.0
+id: pkgB
+key: pkgB
+exposed: True
+exposed-modules: B
+import-dirs: ${pkgroot}/pkgB
+library-dirs: ${pkgroot}/pkgB
+dynamic-library-dirs: ${pkgroot}/pkgB
+hs-libraries: HSpkgB
+depends: pkgA
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/905f8723b92cb34e9f1fa7b4306f32c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/905f8723b92cb34e9f1fa7b4306f32c…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Stg/Unarise: constant-folding during unarisation (#25650)
by Marge Bot (@marge-bot) 13 Mar '26
by Marge Bot (@marge-bot) 13 Mar '26
13 Mar '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
6eef855b by Sylvain Henry at 2026-03-13T15:08:18-04:00
Stg/Unarise: constant-folding during unarisation (#25650)
When building an unboxed sum from a literal argument, mkUbxSum
previously emitted a runtime cast via `case primop [lit] of var -> ...`.
This wrapper prevented GHC from recognising the result as a static
StgRhsCon, causing top-level closures to be allocated as thunks instead
of being statically allocated.
Fix: try to perform the numeric literal cast at compile time using
mkLitNumberWrap (wrapping semantics). If successful, return the cast
literal directly with an identity wrapper (no case expression). The
runtime cast path is kept as fallback for non-literal arguments.
Test: codeGen/should_compile/T25650
- - - - -
7 changed files:
- compiler/GHC/Stg/Pipeline.hs
- compiler/GHC/Stg/Unarise.hs
- testsuite/tests/codeGen/should_compile/Makefile
- + testsuite/tests/codeGen/should_compile/T25650.hs
- + testsuite/tests/codeGen/should_compile/T25650.stdout-ws-32
- + testsuite/tests/codeGen/should_compile/T25650.stdout-ws-64
- testsuite/tests/codeGen/should_compile/all.T
Changes:
=====================================
compiler/GHC/Stg/Pipeline.hs
=====================================
@@ -143,7 +143,7 @@ stg2stg logger extra_vars opts this_mod binds
StgUnarise -> do
us <- getUniqueSupplyM
liftIO (stg_linter False "Pre-unarise" binds)
- let binds' = {-# SCC "StgUnarise" #-} unarise us (stgPipeline_allowTopLevelConApp opts this_mod) binds
+ let binds' = {-# SCC "StgUnarise" #-} unarise (stgPlatform opts) us (stgPipeline_allowTopLevelConApp opts this_mod) binds
liftIO (dump_when Opt_D_dump_stg_unarised "Unarised STG:" binds')
liftIO (stg_linter True "Unarise" binds')
return binds'
=====================================
compiler/GHC/Stg/Unarise.hs
=====================================
@@ -413,6 +413,7 @@ import Data.Maybe (mapMaybe)
import qualified Data.IntMap as IM
import GHC.Builtin.PrimOps
import GHC.Builtin.PrimOps.Casts
+import GHC.Platform
import Data.List (mapAccumL)
-- import GHC.Utils.Trace
@@ -441,12 +442,13 @@ import Data.List (mapAccumL)
-- (i.e. no unboxed tuples, sums or voids)
--
data UnariseEnv = UnariseEnv
- { ue_rho :: (VarEnv UnariseVal)
+ { ue_platform :: !Platform
+ , ue_rho :: VarEnv UnariseVal
, ue_allow_static_conapp :: DataCon -> [StgArg] -> Bool
}
-initUnariseEnv :: VarEnv UnariseVal -> (DataCon -> [StgArg] -> Bool) -> UnariseEnv
-initUnariseEnv = UnariseEnv
+initUnariseEnv :: Platform -> VarEnv UnariseVal -> (DataCon -> [StgArg] -> Bool) -> UnariseEnv
+initUnariseEnv platform rho is_dll = UnariseEnv platform rho is_dll
data UnariseVal
= MultiVal [OutStgArg] -- MultiVal to tuple. Can be empty list (void).
@@ -479,8 +481,8 @@ lookupRho env v = lookupVarEnv (ue_rho env) v
--------------------------------------------------------------------------------
-unarise :: UniqSupply -> (DataCon -> [StgArg] -> Bool) -> [StgTopBinding] -> [StgTopBinding]
-unarise us is_dll_con_app binds = initUs_ us (mapM (unariseTopBinding (initUnariseEnv emptyVarEnv is_dll_con_app)) binds)
+unarise :: Platform -> UniqSupply -> (DataCon -> [StgArg] -> Bool) -> [StgTopBinding] -> [StgTopBinding]
+unarise platform us is_dll_con_app binds = initUs_ us (mapM (unariseTopBinding (initUnariseEnv platform emptyVarEnv is_dll_con_app)) binds)
unariseTopBinding :: UnariseEnv -> StgTopBinding -> UniqSM StgTopBinding
unariseTopBinding rho (StgTopLifted bind)
@@ -627,7 +629,7 @@ unariseUbxSumOrTupleArgs rho us dc args ty_args
| isUnboxedSumDataCon dc
, let args1 = assert (isSingleton args) (unariseConArgs rho args)
- = let (args2, cast_wrapper) = mkUbxSum dc ty_args args1 us
+ = let (args2, cast_wrapper) = mkUbxSum (ue_platform rho) dc ty_args args1 us
in (args2, Just cast_wrapper)
| otherwise
@@ -848,29 +850,29 @@ mapSumIdBinders alt_bndr args rhs rho0
-- right type.
-- Select only the args which contain parts of the current field.
id_arg_exprs = [ args !! i | i <- layout1 ]
- id_vars = [v | StgVarArg v <- id_arg_exprs]
- typed_id_arg_input = assert (equalLength id_vars fld_reps) $
- zip3 id_vars fld_reps uss
-
- mkCastInput :: (Id,PrimRep,UniqSupply) -> ([(PrimOp,Type,Unique)],Id,Id)
- mkCastInput (id,rep,bndr_us) =
- let (ops,types) = unzip $ getCasts (typePrimRepU $ idType id) rep
+ typed_id_arg_input = assert (equalLength id_arg_exprs fld_reps) $
+ zip3 id_arg_exprs fld_reps uss
+
+ -- Process each (arg, target rep, unique supply) to produce
+ -- (rhs wrapper, typed arg). Handles both literal and variable args.
+ -- Literal args can arise after constant-folding in mkUbxSum
+ -- (see Note [Constant-folding during unarisation]).
+ mkCastArg :: (StgArg, PrimRep, UniqSupply) -> (StgExpr -> StgExpr, StgArg)
+ mkCastArg (StgLitArg lit, rep, _us)
+ | Just lit' <- castLiteralArg (ue_platform rho0) rep lit
+ = (id, StgLitArg lit')
+ | otherwise = pprPanic "mapSumIdBinders: cannot cast literal" (ppr lit $$ ppr rep)
+ mkCastArg (StgVarArg v, rep, bndr_us) =
+ let (ops,types) = unzip $ getCasts (typePrimRepU $ idType v) rep
cst_opts = zip3 ops types $ uniqsFromSupply bndr_us
out_id = case cst_opts of
- [] -> id
- _ -> let (_,ty,uq) = last cst_opts
- in mkCastVar uq ty
- in (cst_opts,id,out_id)
-
- cast_inputs = map mkCastInput typed_id_arg_input
- (rhs_with_casts,typed_ids) = mapAccumL cast_arg (\x->x) cast_inputs
- where
- cast_arg rhs_in (cast_ops,in_id,out_id) =
- let rhs_out = castArgRename cast_ops (StgVarArg in_id)
- in (rhs_in . rhs_out, out_id)
+ [] -> v
+ _ -> let (_,ty,uq) = last cst_opts in mkCastVar uq ty
+ in (castArgRename cst_opts (StgVarArg v), StgVarArg out_id)
- typed_id_args = map StgVarArg typed_ids
+ (wrappers, typed_id_args) = unzip $ map mkCastArg typed_id_arg_input
+ rhs_with_casts = foldr (.) id wrappers
if isMultiValBndr alt_bndr
then return (extendRho rho0 alt_bndr (MultiVal typed_id_args), rhs_with_casts rhs)
@@ -913,14 +915,15 @@ mkCast arg_in cast_op out_id out_ty in_rhs =
--
mkUbxSum
:: HasDebugCallStack
- => DataCon -- Sum data con
+ => Platform -- For compile-time constant-folding
+ -> DataCon -- Sum data con
-> [[PrimRep]] -- Representations of type arguments of the sum data con
-> [OutStgArg] -- Actual arguments of the alternative.
-> UniqSupply
-> ([OutStgArg] -- Final tuple arguments
,(StgExpr->StgExpr) -- We might need to cast the args first
)
-mkUbxSum dc ty_args args0 us
+mkUbxSum platform dc ty_args args0 us
= let
tag_slot :| sum_slots = ubxSumRepType ty_args
-- drop tag slot
@@ -961,6 +964,11 @@ mkUbxSum dc ty_args args0 us
, ubxSumRubbishArg slot)
castArg :: UniqSupply -> SlotTy -> StgArg -> Maybe (StgArg,UniqSupply,StgExpr -> StgExpr)
+ castArg us slot_ty arg@(StgLitArg lit)
+ -- See Note [Constant-folding during unarisation]
+ | slotPrimRep slot_ty /= stgArgRepU arg
+ , Just lit' <- castLiteralArg platform (slotPrimRep slot_ty) lit
+ = Just (StgLitArg lit', us, id)
castArg us slot_ty arg
-- Cast the argument to the type of the slot if required
| slotPrimRep slot_ty /= stgArgRepU arg
@@ -1006,6 +1014,101 @@ ubxSumRubbishArg DoubleSlot = StgLitArg (LitDouble 0)
ubxSumRubbishArg (VecSlot n e) = StgLitArg (LitRubbish TypeLike vec_rep)
where vec_rep = primRepToRuntimeRep (VecRep n e)
+{-
+Note [Constant-folding during unarisation]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+See #25650.
+
+Goal: ensure that top-level bindings whose unboxed-sum fields are literals
+become statically allocated closures (i.e. compile-time constants in the
+object file) rather than CAFs.
+
+Background: A top-level RHS is statically allocated when it is a plain
+`StgRhsCon`: a data constructor applied to arguments with no surrounding
+expression. Any `StgCase` wrapper, even one that is a no-op at runtime, turns
+the RHS into a CAF.
+
+The problem: When `mkUbxSum` builds an unboxed sum whose argument PrimRep does
+not match the slot PrimRep, the general `castArg` path emits a runtime conversion
+wrapper:
+
+ case <conversion_primop> arg of x' -> <rhs using x'>
+
+For a *variable* argument this is unavoidable, the value is not known at
+compile time. For a *literal* argument, however, the conversion can be performed
+at compile time, avoiding the `StgCase` wrapper entirely.
+
+Example
+~~~~~~~
+Consider:
+
+ data A = MkA (# Int16# | Int32# #)
+ foo = MkA (# 10#Int16 | #)
+
+By the time this gets to the end of the Simplifier pipeline, this still looks
+like:
+ foo = MkA (# 10#Int16 | #)
+That is: the worker for the data constructor takes an unboxed sum as its
+argument.
+
+The Unarise pass, which works on STG, decides that
+ (# 10#Int16 | #) :: (# Int16# | Int32# #)
+should be represented as an pair of an integer tag (of type `Int8#`) and a payload
+value (of type `Word32#`). But to do that it has to convert `10#Int16` into
+`Word32#`, and that conversion is not a no-op. So without constant-folding we
+get:
+
+ foo =
+ \u []
+ case int16ToWord16# [10#Int16] of cst_sum_gio {
+ __DEFAULT ->
+ case word16ToWord# [cst_sum_gio] of cst_sum_gip {
+ __DEFAULT -> MkA [1# cst_sum_gip];
+ };
+ };
+
+Note that in the output of the unarise pass, the worker `MkA` takes two
+arguments: the tag and the payload of our unboxed sum..
+
+However it's a bit silly to generate a CAF here because with some
+constant-folding we can easily avoid this thunk and generate a static datacon
+instead. That's why the literal clause of `castArg` intercepts `Int16# 10`,
+calls `castLiteralArg` to compute `Word32# 10` at compile time, and returns the
+identity wrapper. The result is:
+
+ foo = MkA! [1#Word8 10#Word32];
+
+
+Note that `castLiteralArg` uses `mkLitNumberWrap`, which matches the
+semantics of GHC's integer-conversion primops (zero/sign extension to the target
+width) — exactly the same transformation the runtime conversion would have
+performed.
+
+-}
+
+-- | Try to convert a numeric literal to a new PrimRep at compile time.
+-- Uses wrapping semantics (same as GHC's integer conversion primops).
+-- Returns Nothing for non-numeric literals or unsupported PrimReps.
+-- See Note [Constant-folding during unarisation].
+castLiteralArg :: Platform -> PrimRep -> Literal -> Maybe Literal
+castLiteralArg platform to_rep (LitNumber _ n)
+ | Just to_ty <- litNumTypeFromPrimRep to_rep
+ = Just (mkLitNumberWrap platform to_ty n)
+castLiteralArg _ _ _ = Nothing
+
+litNumTypeFromPrimRep :: PrimRep -> Maybe LitNumType
+litNumTypeFromPrimRep WordRep = Just LitNumWord
+litNumTypeFromPrimRep Word8Rep = Just LitNumWord8
+litNumTypeFromPrimRep Word16Rep = Just LitNumWord16
+litNumTypeFromPrimRep Word32Rep = Just LitNumWord32
+litNumTypeFromPrimRep Word64Rep = Just LitNumWord64
+litNumTypeFromPrimRep IntRep = Just LitNumInt
+litNumTypeFromPrimRep Int8Rep = Just LitNumInt8
+litNumTypeFromPrimRep Int16Rep = Just LitNumInt16
+litNumTypeFromPrimRep Int32Rep = Just LitNumInt32
+litNumTypeFromPrimRep Int64Rep = Just LitNumInt64
+litNumTypeFromPrimRep _ = Nothing
+
--------------------------------------------------------------------------------
{-
=====================================
testsuite/tests/codeGen/should_compile/Makefile
=====================================
@@ -80,3 +80,6 @@ T17648:
T25166:
'$(TEST_HC)' $(TEST_HC_OPTS) -O2 -dno-typeable-binds -ddump-cmm T25166.hs | awk '/foo_closure/{flag=1}/}]/{flag=0}flag'
+
+T25650:
+ '$(TEST_HC)' $(TEST_HC_OPTS) -O2 -dno-typeable-binds -ddump-cmm T25650.hs | awk '/baz_foo_closure|baz_bar_closure/{flag=1}/}]/{flag=0}flag'
=====================================
testsuite/tests/codeGen/should_compile/T25650.hs
=====================================
@@ -0,0 +1,17 @@
+module T25650 (baz_foo, baz_bar) where
+
+import Data.Word
+
+data A
+ = A1 {-# UNPACK #-} !Word32
+ | A2 {-# UNPACK #-} !B
+
+data B = B1 | B2
+
+foo = A1 10
+bar = A2 B2
+
+data C = C {-# UNPACK #-} !A
+
+baz_foo = C foo
+baz_bar = C bar
=====================================
testsuite/tests/codeGen/should_compile/T25650.stdout-ws-32
=====================================
@@ -0,0 +1,14 @@
+[section ""data" . T25650.baz_foo_closure" {
+ T25650.baz_foo_closure:
+ const T25650.C_con_info;
+ const 10;
+ const 1 :: W8;
+ const 0 :: W8;
+ const 0 :: W16;
+[section ""data" . T25650.baz_bar_closure" {
+ T25650.baz_bar_closure:
+ const T25650.C_con_info;
+ const 2;
+ const 2 :: W8;
+ const 0 :: W8;
+ const 0 :: W16;
=====================================
testsuite/tests/codeGen/should_compile/T25650.stdout-ws-64
=====================================
@@ -0,0 +1,14 @@
+[section ""data" . T25650.baz_foo_closure" {
+ T25650.baz_foo_closure:
+ const T25650.C_con_info;
+ const 10 :: W32;
+ const 1 :: W8;
+ const 0 :: W8;
+ const 0 :: W16;
+[section ""data" . T25650.baz_bar_closure" {
+ T25650.baz_bar_closure:
+ const T25650.C_con_info;
+ const 2 :: W32;
+ const 2 :: W8;
+ const 0 :: W8;
+ const 0 :: W16;
=====================================
testsuite/tests/codeGen/should_compile/all.T
=====================================
@@ -140,6 +140,7 @@ test('callee-no-local', [
)
test('T25166', [req_cmm], makefile_test, [])
+test('T25650', [req_cmm], makefile_test, [])
# dump Core to ensure that d is defined as: d = D 10## RUBBISH(IntRep)
test('T25177', normal, compile, ['-O2 -dno-typeable-binds -ddump-simpl -dsuppress-all -dsuppress-uniques -v0'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6eef855b6b7fadb9038dfb52b95d0e5…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6eef855b6b7fadb9038dfb52b95d0e5…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] ghc-internal: move bits Weak of finalizer interface to base
by Marge Bot (@marge-bot) 13 Mar '26
by Marge Bot (@marge-bot) 13 Mar '26
13 Mar '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
a27dc081 by Teo Camarasu at 2026-03-13T15:06:51-04:00
ghc-internal: move bits Weak of finalizer interface to base
We move parts of the Weak finalizer interface to `base` only the parts
that the RTS needs to know about are kept in `ghc-internal`.
This lets us then prune our imports somewhat and get rid of some SOURCE imports.
Resolves #26985
- - - - -
9 changed files:
- libraries/base/src/GHC/Weak.hs
- libraries/base/src/GHC/Weak/Finalize.hs
- − libraries/base/src/GHC/Weak/Finalizehs
- libraries/base/src/System/Mem/Weak.hs
- − libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs-boot
- − libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs-boot
- libraries/ghc-internal/src/GHC/Internal/TopHandler.hs
- libraries/ghc-internal/src/GHC/Internal/Weak.hs
- libraries/ghc-internal/src/GHC/Internal/Weak/Finalize.hs
Changes:
=====================================
libraries/base/src/GHC/Weak.hs
=====================================
@@ -29,3 +29,5 @@ module GHC.Weak
) where
import GHC.Internal.Weak
+import GHC.Internal.Weak.Finalize
+import GHC.Weak.Finalize
=====================================
libraries/base/src/GHC/Weak/Finalize.hs
=====================================
@@ -14,9 +14,14 @@ module GHC.Weak.Finalize
import GHC.Internal.Weak.Finalize
--- These imports can be removed once runFinalizerBatch is removed,
--- as can MagicHash above.
-import GHC.Internal.Base (Int, Array#, IO, State#, RealWorld)
+import GHC.Internal.Base
+import GHC.Internal.Exception
+import GHC.Internal.IORef
+import GHC.Internal.Conc.Sync (labelThreadByteArray#, myThreadId)
+import GHC.Internal.IO (catchException, unsafePerformIO)
+import GHC.Internal.IO.Handle.Types (Handle)
+import GHC.Internal.IO.Handle.Text (hPutStrLn)
+import GHC.Internal.Encoding.UTF8 (utf8EncodeByteArray#)
{-# DEPRECATED runFinalizerBatch
@@ -36,3 +41,13 @@ runFinalizerBatch :: Int
-> Array# (State# RealWorld -> State# RealWorld)
-> IO ()
runFinalizerBatch = GHC.Internal.Weak.Finalize.runFinalizerBatch
+
+-- | An exception handler for 'Handle' finalization that prints the error to
+-- the given 'Handle', but doesn't rethrow it.
+--
+-- @since base-4.18.0.0
+printToHandleFinalizerExceptionHandler :: Handle -> SomeException -> IO ()
+printToHandleFinalizerExceptionHandler hdl se =
+ hPutStrLn hdl msg `catchException` (\(SomeException _) -> return ())
+ where
+ msg = "Exception during weak pointer finalization (ignored): " ++ displayException se ++ "\n"
=====================================
libraries/base/src/GHC/Weak/Finalizehs deleted
=====================================
=====================================
libraries/base/src/System/Mem/Weak.hs
=====================================
@@ -91,6 +91,7 @@ module System.Mem.Weak (
import Prelude
import GHC.Internal.Weak
+import GHC.Weak
-- | A specialised version of 'mkWeak', where the key and the value are
-- the same object:
=====================================
libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs-boot deleted
=====================================
@@ -1,70 +0,0 @@
-{-# LANGUAGE MagicHash, NoImplicitPrelude #-}
-{-# OPTIONS_HADDOCK not-home #-}
-
------------------------------------------------------------------------------
--- |
--- Module : GHC.Internal.Conc.Sync [boot]
--- Copyright : (c) The University of Glasgow, 1994-2002
--- License : see libraries/base/LICENSE
---
--- Maintainer : ghc-devs(a)haskell.org
--- Stability : internal
--- Portability : non-portable (GHC extensions)
---
--- Basic concurrency stuff.
---
------------------------------------------------------------------------------
-
-module GHC.Internal.Conc.Sync
- ( forkIO,
- ThreadId(..),
- myThreadId,
- showThreadId,
- ThreadStatus(..),
- threadStatus,
- sharedCAF,
- labelThreadByteArray#
- ) where
-
-import GHC.Internal.Base
-import GHC.Internal.Ptr
-
-forkIO :: IO () -> IO ThreadId
-
-data ThreadId = ThreadId ThreadId#
-
-data BlockReason
- = BlockedOnMVar
- -- ^blocked on 'MVar'
- {- possibly (see 'threadstatus' below):
- | BlockedOnMVarRead
- -- ^blocked on reading an empty 'MVar'
- -}
- | BlockedOnBlackHole
- -- ^blocked on a computation in progress by another thread
- | BlockedOnException
- -- ^blocked in 'throwTo'
- | BlockedOnSTM
- -- ^blocked in 'retry' in an STM transaction
- | BlockedOnForeignCall
- -- ^currently in a foreign call
- | BlockedOnOther
- -- ^blocked on some other resource. Without @-threaded@,
- -- I\/O and 'threadDelay' show up as 'BlockedOnOther', with @-threaded@
- -- they show up as 'BlockedOnMVar'.
-
-data ThreadStatus
- = ThreadRunning
- -- ^the thread is currently runnable or running
- | ThreadFinished
- -- ^the thread has finished
- | ThreadBlocked BlockReason
- -- ^the thread is blocked on some resource
- | ThreadDied
- -- ^the thread received an uncaught exception
-
-myThreadId :: IO ThreadId
-showThreadId :: ThreadId -> String
-threadStatus :: ThreadId -> IO ThreadStatus
-sharedCAF :: a -> (Ptr a -> IO (Ptr a)) -> IO a
-labelThreadByteArray# :: ThreadId -> ByteArray# -> IO ()
=====================================
libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs-boot deleted
=====================================
@@ -1,8 +0,0 @@
-{-# LANGUAGE NoImplicitPrelude #-}
-
-module GHC.Internal.IO.Handle.Text ( hPutStrLn ) where
-
-import GHC.Internal.Base (String, IO)
-import {-# SOURCE #-} GHC.Internal.IO.Handle.Types (Handle)
-
-hPutStrLn :: Handle -> String -> IO ()
=====================================
libraries/ghc-internal/src/GHC/Internal/TopHandler.hs
=====================================
@@ -50,6 +50,8 @@ import GHC.Internal.IO.Handle
import GHC.Internal.IO.StdHandles
import GHC.Internal.IO.Exception
import GHC.Internal.Weak
+import GHC.Internal.Weak.Finalize
+import GHC.Internal.IO.Handle.Types ()
#if defined(mingw32_HOST_OS)
import GHC.Internal.ConsoleHandler as GHC.ConsoleHandler
=====================================
libraries/ghc-internal/src/GHC/Internal/Weak.hs
=====================================
@@ -24,19 +24,9 @@ module GHC.Internal.Weak (
mkWeak,
deRefWeak,
finalize,
-
- -- * Handling exceptions
- -- | When an exception is thrown by a finalizer called by the
- -- garbage collector, GHC calls a global handler which can be set with
- -- 'setFinalizerExceptionHandler'. Note that any exceptions thrown by
- -- this handler will be ignored.
- setFinalizerExceptionHandler,
- getFinalizerExceptionHandler,
- printToHandleFinalizerExceptionHandler
) where
import GHC.Internal.Base
-import GHC.Internal.Weak.Finalize
{-|
A weak pointer object with a key and a value. The value has type @v@.
=====================================
libraries/ghc-internal/src/GHC/Internal/Weak/Finalize.hs
=====================================
@@ -4,26 +4,17 @@
{-# LANGUAGE Unsafe #-}
module GHC.Internal.Weak.Finalize
- ( -- * Handling exceptions
- -- | When an exception is thrown by a finalizer called by the
- -- garbage collector, GHC calls a global handler which can be set with
- -- 'setFinalizerExceptionHandler'. Note that any exceptions thrown by
- -- this handler will be ignored.
- setFinalizerExceptionHandler
- , getFinalizerExceptionHandler
- , printToHandleFinalizerExceptionHandler
- -- * Internal
+ ( getFinalizerExceptionHandler
+ , setFinalizerExceptionHandler
, runFinalizerBatch
) where
import GHC.Internal.Base
-import GHC.Internal.Exception
-import GHC.Internal.IORef
-import {-# SOURCE #-} GHC.Internal.Conc.Sync (labelThreadByteArray#, myThreadId)
-import GHC.Internal.IO (catchException, unsafePerformIO)
-import {-# SOURCE #-} GHC.Internal.IO.Handle.Types (Handle)
-import {-# SOURCE #-} GHC.Internal.IO.Handle.Text (hPutStrLn)
-import GHC.Internal.Encoding.UTF8 (utf8EncodeByteArray#)
+import GHC.Internal.Conc.Sync ( labelThreadByteArray#, myThreadId )
+import GHC.Internal.Encoding.UTF8 ( utf8EncodeByteArray# )
+import GHC.Internal.Exception ( SomeException(..) )
+import GHC.Internal.IO ( catchException, unsafePerformIO )
+import GHC.Internal.IORef ( IORef, newIORef, readIORef, writeIORef )
data ByteArray = ByteArray ByteArray#
@@ -82,13 +73,3 @@ getFinalizerExceptionHandler = readIORef finalizerExceptionHandler
-- @since base-4.18.0.0
setFinalizerExceptionHandler :: (SomeException -> IO ()) -> IO ()
setFinalizerExceptionHandler = writeIORef finalizerExceptionHandler
-
--- | An exception handler for 'Handle' finalization that prints the error to
--- the given 'Handle', but doesn't rethrow it.
---
--- @since base-4.18.0.0
-printToHandleFinalizerExceptionHandler :: Handle -> SomeException -> IO ()
-printToHandleFinalizerExceptionHandler hdl se =
- hPutStrLn hdl msg `catchException` (\(SomeException _) -> return ())
- where
- msg = "Exception during weak pointer finalization (ignored): " ++ displayException se ++ "\n"
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a27dc08195bc7572866e676009033f0…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a27dc08195bc7572866e676009033f0…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] hadrian: remove redundant library/rts ways definitions from stock flavours
by Marge Bot (@marge-bot) 13 Mar '26
by Marge Bot (@marge-bot) 13 Mar '26
13 Mar '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
669d09f9 by Cheng Shao at 2026-03-13T15:06:07-04:00
hadrian: remove redundant library/rts ways definitions from stock flavours
This patch removes redundant library/rts ways definitions from stock
flavours in hadrian; they can be replaced by applying appropriate
filters on `defaultFlavour`.
- - - - -
5 changed files:
- hadrian/src/Settings/Flavours/Development.hs
- hadrian/src/Settings/Flavours/GhcInGhci.hs
- hadrian/src/Settings/Flavours/Quick.hs
- hadrian/src/Settings/Flavours/QuickCross.hs
- hadrian/src/Settings/Flavours/Quickest.hs
Changes:
=====================================
hadrian/src/Settings/Flavours/Development.hs
=====================================
@@ -1,21 +1,15 @@
module Settings.Flavours.Development (developmentFlavour) where
-import qualified Data.Set as Set
-
import Expression
import Flavour
-import Oracles.Flag
import Packages
import {-# SOURCE #-} Settings.Default
-- Please update doc/flavours.md when changing this file.
developmentFlavour :: Stage -> Flavour
-developmentFlavour ghcStage = defaultFlavour
+developmentFlavour ghcStage = disableDynamicLibs $ disableProfiledLibs $ defaultFlavour
{ name = "devel" ++ stageString ghcStage
, extraArgs = developmentArgs ghcStage <> defaultHaddockExtraArgs
- , libraryWays = pure $ Set.fromList [vanilla]
- , rtsWays = Set.fromList <$> mconcat [pure [vanilla, debug], targetSupportsThreadedRts ? pure [threaded, threadedDebug]]
- , dynamicGhcPrograms = return False
, ghcDebugAssertions = (== ghcStage) }
where
stageString Stage2 = "2"
=====================================
hadrian/src/Settings/Flavours/GhcInGhci.hs
=====================================
@@ -1,22 +1,14 @@
module Settings.Flavours.GhcInGhci (ghcInGhciFlavour) where
-import qualified Data.Set as Set
-
import Expression
import Flavour
-import Oracles.Flag
import {-# SOURCE #-} Settings.Default
-- Please update doc/flavours.md when changing this file.
ghcInGhciFlavour :: Flavour
-ghcInGhciFlavour = defaultFlavour
+ghcInGhciFlavour = disableProfiledLibs $ defaultFlavour
{ name = "ghc-in-ghci"
, extraArgs = ghciArgs
- -- We can't build DLLs on Windows (yet). Actually we should only
- -- include the dynamic way when we have a dynamic host GHC, but just
- -- checking for Windows seems simpler for now.
- , libraryWays = pure (Set.fromList [vanilla]) <> pure (Set.fromList [ dynamic | not windowsHost ])
- , rtsWays = pure (Set.fromList [vanilla]) <> (targetSupportsThreadedRts ? pure (Set.fromList [threaded])) <> pure (Set.fromList [ dynamic | not windowsHost ])
}
ghciArgs :: Args
=====================================
hadrian/src/Settings/Flavours/Quick.hs
=====================================
@@ -4,33 +4,16 @@ module Settings.Flavours.Quick
)
where
-import qualified Data.Set as Set
-
import Expression
import Flavour
-import Oracles.Flag
import {-# SOURCE #-} Settings.Default
-- Please update doc/flavours.md when changing this file.
quickFlavour :: Flavour
-quickFlavour = defaultFlavour
+quickFlavour = disableProfiledLibs $ defaultFlavour
{ name = "quick"
, extraArgs = quickArgs
- , libraryWays = Set.fromList <$>
- mconcat
- [ pure [vanilla]
- , notStage0 ? platformSupportsSharedLibs ? pure [dynamic] ]
- , rtsWays = Set.fromList <$>
- mconcat
- [ pure
- [ vanilla, debug ]
- , targetSupportsThreadedRts ? pure [ threaded, threadedDebug ]
- , notStage0 ? platformSupportsSharedLibs ? pure
- [ dynamic, debugDynamic ]
- , notStage0 ? platformSupportsSharedLibs ? targetSupportsThreadedRts ? pure [
- threadedDynamic, threadedDebugDynamic
- ]
- ] }
+ }
quickArgs :: Args
quickArgs = sourceArgs SourceArgs
=====================================
hadrian/src/Settings/Flavours/QuickCross.hs
=====================================
@@ -1,33 +1,16 @@
module Settings.Flavours.QuickCross (quickCrossFlavour) where
-import qualified Data.Set as Set
-
import Expression
import Flavour
-import Oracles.Flag
import {-# SOURCE #-} Settings.Default
-- Please update doc/flavours.md when changing this file.
quickCrossFlavour :: Flavour
-quickCrossFlavour = defaultFlavour
+quickCrossFlavour = disableProfiledLibs $ defaultFlavour
{ name = "quick-cross"
, extraArgs = quickCrossArgs
, dynamicGhcPrograms = pure False
- , libraryWays = Set.fromList <$>
- mconcat
- [ pure [vanilla]
- , notStage0 ? platformSupportsSharedLibs ? pure [dynamic] ]
- , rtsWays = Set.fromList <$>
- mconcat
- [ pure
- [ vanilla, debug ]
- , targetSupportsThreadedRts ? pure [threaded, threadedDebug]
- , notStage0 ? platformSupportsSharedLibs ? pure
- [ dynamic, debugDynamic ]
- , notStage0 ? platformSupportsSharedLibs ? targetSupportsThreadedRts ? pure [
- threadedDynamic, threadedDebugDynamic
- ]
- ] }
+ }
quickCrossArgs :: Args
quickCrossArgs = sourceArgs SourceArgs
=====================================
hadrian/src/Settings/Flavours/Quickest.hs
=====================================
@@ -1,20 +1,15 @@
module Settings.Flavours.Quickest (quickestFlavour) where
-import qualified Data.Set as Set
-
import Expression
import Flavour
-import Oracles.Flag
import {-# SOURCE #-} Settings.Default
-- Please update doc/flavours.md when changing this file.
quickestFlavour :: Flavour
-quickestFlavour = defaultFlavour
+quickestFlavour = disableDynamicLibs $ disableProfiledLibs $ defaultFlavour
{ name = "quickest"
, extraArgs = quickestArgs
- , libraryWays = pure (Set.fromList [vanilla])
- , rtsWays = pure (Set.fromList [vanilla]) <> (targetSupportsThreadedRts ? pure (Set.fromList [threaded]))
- , dynamicGhcPrograms = return False }
+ }
quickestArgs :: Args
quickestArgs = sourceArgs SourceArgs
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/669d09f950a6e88b903d9fd8a757153…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/669d09f950a6e88b903d9fd8a757153…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] DmdAnal: Take stable unfoldings into account when determining argument demands
by Marge Bot (@marge-bot) 13 Mar '26
by Marge Bot (@marge-bot) 13 Mar '26
13 Mar '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
870243e4 by Zubin Duggal at 2026-03-12T17:33:28+05:30
DmdAnal: Take stable unfoldings into account when determining argument demands
Previously, demand analysis only looked at the RHS to compute argument demands.
If the optimised RHS discarded uses of an argument that the stable unfolding
still needed, it would be incorrectly marked absent. Worker/wrapper would then
replace it with LitRubbish, and inlining the stable unfolding would use the
rubbish value, causing a segfault.
To fix, we introduce addUnfoldingDemands which analyses the stable unfolding
with dmdAnal and combines its DmdType with the RHS's via the new `maxDmdType`
which combines the demands of the stable unfolding with the rhs, so we can avoid
any situation where we give an absent demand to something which is still used
by the stable unfolding.
Fixes #26416.
- - - - -
8 changed files:
- compiler/GHC/Core/Opt/DmdAnal.hs
- compiler/GHC/Types/Demand.hs
- testsuite/tests/dmdanal/should_compile/T18894.stderr
- + testsuite/tests/dmdanal/should_run/M1.hs
- + testsuite/tests/dmdanal/should_run/T26416.hs
- + testsuite/tests/dmdanal/should_run/T26416.stdout
- testsuite/tests/dmdanal/should_run/all.T
- testsuite/tests/dmdanal/sigs/T21081.stderr
Changes:
=====================================
compiler/GHC/Core/Opt/DmdAnal.hs
=====================================
@@ -23,7 +23,7 @@ import GHC.Core.DataCon
import GHC.Core.Utils
import GHC.Core.TyCon
import GHC.Core.Type
-import GHC.Core.FVs ( rulesRhsFreeIds, bndrRuleAndUnfoldingIds )
+import GHC.Core.FVs ( rulesRhsFreeIds, bndrRuleAndUnfoldingIds, idRuleVars )
import GHC.Core.Coercion ( Coercion )
import GHC.Core.TyCo.FVs ( coVarsOfCos )
import GHC.Core.TyCo.Compare ( eqType )
@@ -1106,9 +1106,22 @@ dmdAnalRhsSig top_lvl rec_flag env let_sd id rhs
rhs_sd = mkCalledOnceDmds ww_arity adjusted_body_sd
WithDmdType rhs_dmd_ty rhs' = dmdAnal env rhs_sd rhs
- DmdType rhs_env rhs_dmds = rhs_dmd_ty
- (final_rhs_dmds, final_rhs) = finaliseArgBoxities env id ww_arity
- rhs_dmds (de_div rhs_env) rhs'
+
+ -- See Note [Absence analysis for stable unfoldings and RULES], Wrinkle (W3)
+ full_dmd_ty = addUnfoldingDemands env rhs_sd id rhs_dmd_ty
+ DmdType full_rhs_env combined_rhs_dmds = full_dmd_ty
+
+ final_rhs_dmds = finaliseArgBoxities env id ww_arity
+ combined_rhs_dmds (de_div full_rhs_env) rhs'
+
+ -- Attach the final demands to the lambda binders of the RHS.
+ -- IMPORTANT: The lambda binders of final_rhs must carry the final demand
+ -- info, because worker/wrapper drives decisions from the idDemandInfo on
+ -- the lambdas (see mkWwstr_one), NOT from the strictness signature of the
+ -- function. So the demands must reflect both the unfolding combination
+ -- (from addUnfoldingDemands) and the boxity finalisation (from
+ -- finaliseArgBoxities).
+ final_rhs = setLamDmds final_rhs_dmds rhs'
dmd_sig_arity = ww_arity + strictCallArity body_sd
sig = mkDmdSigForArity dmd_sig_arity (DmdType sig_env final_rhs_dmds)
@@ -1132,19 +1145,51 @@ dmdAnalRhsSig top_lvl rec_flag env let_sd id rhs
-- we never get used-once info for FVs of recursive functions.
-- See #14816 where we try to get rid of reuseEnv.
rhs_env1 = case rec_flag of
- Recursive -> reuseEnv rhs_env
- NonRecursive -> rhs_env
+ Recursive -> reuseEnv full_rhs_env
+ NonRecursive -> full_rhs_env
-- See Note [Absence analysis for stable unfoldings and RULES]
- rhs_env2 = rhs_env1 `plusDmdEnv` demandRootSet env (bndrRuleAndUnfoldingIds id)
+ -- The unfolding FVs are already included in full_rhs_env via addUnfoldingDemands.
+ -- Here we only need demandRoots for RULES.
+ rhs_env2 = rhs_env1 `plusDmdEnv` demandRootSet env (filterVarSet isId (idRuleVars id))
-- See Note [Lazy and unleashable free variables]
!(!sig_env, !weak_fvs) = splitWeakDmds rhs_env2
+setLamDmds :: [Demand] -> CoreExpr -> CoreExpr
+-- Attach the demands to the outer lambdas of this expression
+setLamDmds (dmd:dmds) (Lam v e)
+ | isTyVar v = Lam v (setLamDmds (dmd:dmds) e)
+ | otherwise = Lam (v `setIdDemandInfo` dmd) (setLamDmds dmds e)
+setLamDmds dmds (Cast e co) = Cast (setLamDmds dmds e) co
+ -- This case happens for an OPAQUE function, which may look like
+ -- f = (\x y. blah) |> co
+ -- We give it strictness but no boxity (#22502)
+setLamDmds _ e = e
+ -- In the OPAQUE case, the list of demands at this point might be
+ -- non-empty, e.g., when looking at a PAP. Hence don't panic (#22997).
+
splitWeakDmds :: DmdEnv -> (DmdEnv, WeakDmds)
splitWeakDmds (DE fvs div) = (DE sig_fvs div, weak_fvs)
where (!weak_fvs, !sig_fvs) = partitionVarEnv isWeakDmd fvs
+-- | If there is a stable unfolding, combine argument demands and free variable
+-- demands from the unfolding with those from the RHS.
+-- See Note [Absence analysis for stable unfoldings and RULES], Wrinkle (W3).
+-- See Note [Combining demands for stable unfoldings] in GHC.Types.Demand.
+addUnfoldingDemands :: AnalEnv -> SubDemand -> Id -> DmdType -> DmdType
+addUnfoldingDemands env rhs_sd id rhs_dmd_ty
+ | isStableUnfolding unf
+ , Just unf_body <- maybeUnfoldingTemplate unf
+ , let WithDmdType unf_dmd_ty _ = dmdAnal env rhs_sd unf_body
+ = -- pprTrace "addUnfoldingDemands" (ppr id $$ ppr rhs_dmd_ty $$ ppr unf_dmd_ty) $
+ maxDmdType rhs_dmd_ty unf_dmd_ty
+
+ | otherwise
+ = rhs_dmd_ty -- No stable unfolding, nothing to do
+ where
+ unf = realIdUnfolding id
+
-- | The result type after applying 'idArity' many arguments. Returns 'Nothing'
-- when the type doesn't have exactly 'idArity' many arrows.
resultType_maybe :: Id -> Maybe Type
@@ -1482,10 +1527,21 @@ and transform to
Now if f is subsequently inlined, we'll use 'g' and ... disaster.
-SOLUTION: if f has a stable unfolding, treat every free variable as a
-/demand root/, that is: Analyse it as if it was a variable occurring in a
+SOLUTION for stable unfoldings: in `dmdAnalRhsSig`, if the function has a
+stable unfolding, analyse it with `dmdAnal` and combine the resulting `DmdType`
+with the RHS's `DmdType`. This is done by `addUnfoldingDemands`, which uses
+`maxDmdType` to combine both argument demands and free variable demands.
+See Note [Combining demands for stable unfoldings] in GHC.Types.Demand for
+details of the combining operation.
+
+This handles both the free variables and arguments of stable unfoldings in one
+go. For example, in the scenario above, the unfolding's `DmdType` will mention
+`g` as a free variable, so `maxDmdType` will keep it alive.
+
+SOLUTION for RULES: treat every Id free in the RHS of a RULE as a
+/demand root/, that is: analyse it as if it was a variable occurring in a
'topDmd' context. This is done in `demandRoot` (which we also use for exported
-top-level ids). Do the same for Ids free in the RHS of any RULES for f.
+top-level ids).
Wrinkles:
@@ -1502,7 +1558,7 @@ Wrinkles:
this, that actually happened in practice.
(W2) You might wonder why we don't simply take the free vars of the
- unfolding/RULE and map them to topDmd. The reason is that any of the free vars
+ RULE and map them to topDmd. The reason is that any of the free vars
might have demand signatures themselves that in turn demand transitive free
variables and that we hence need to unleash! This came up in #23208.
Consider
@@ -1524,6 +1580,24 @@ Wrinkles:
for `sg`, failing to unleash the signature and hence observed an absent
error instead of the `really important message`.
+ (W3) The stable unfolding solution above handles /free variables/, but
+ what about /arguments/? Consider (#26416)
+
+ fromVector :: (Storable a, KnownNat n) => Vector a -> Vector a
+ fromVector v = ... (uses Storable dictionary) ...
+ {-# INLINABLE fromVector #-}
+
+ Suppose that the optimised RHS of `fromVector` somehow discards the use of
+ the Storable dictionary, but the stable unfolding still uses it. Then the
+ demand signature will say that the Storable dictionary argument is absent,
+ and worker/wrapper will replace it with `LitRubbish`. But when the
+ worker's unfolding is inlined, it will use that rubbish value as a real
+ dictionary, leading to a segfault!
+
+ `addUnfoldingDemands` handles this too: since `maxDmdType` combines both
+ the argument demands and free variable demands from the unfolding's
+ `DmdType` with the RHS's, argument absence is correctly prevented.
+
Note [DmdAnal for DataCon wrappers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We give DataCon wrappers a (necessarily flat) demand signature in
@@ -2001,22 +2075,20 @@ positiveTopBudget (MkB n _) = n >= 0
finaliseArgBoxities :: AnalEnv -> Id -> Arity
-> [Demand] -> Divergence
- -> CoreExpr -> ([Demand], CoreExpr)
+ -> CoreExpr -> [Demand]
-- POSTCONDITION:
--- If: (dmds', rhs') = finaliseArgBoxitities ... dmds .. rhs
+-- If: dmds' = finaliseArgBoxities ... dmds .. rhs
-- Then:
-- dmds' is the same as dmds (including length), except for boxity info
--- rhs' is the same as rhs, except for dmd info on lambda binders
-- NB: For join points, length dmds might be greater than ww_arity
+-- NB: rhs is needed only to count visible binders.
finaliseArgBoxities env fn ww_arity arg_dmds div rhs
-- Check for an OPAQUE function: see Note [OPAQUE pragma]
-- In that case, trim off all boxity info from argument demands
- -- and demand info on lambda binders
-- See Note [The OPAQUE pragma and avoiding the reboxing of arguments]
| isOpaquePragma (idInlinePragma fn)
- , let trimmed_arg_dmds = map trimBoxity arg_dmds
- = (trimmed_arg_dmds, set_lam_dmds trimmed_arg_dmds rhs)
+ = map trimBoxity arg_dmds
-- Check that we have enough visible binders to match the
-- ww arity; if not, we won't do worker/wrapper
@@ -2027,7 +2099,7 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs
-- It's a bit of a corner case. Anyway for now we pass on the
-- unadulterated demands from the RHS, without any boxity trimming.
| ww_arity > count isId bndrs
- = (arg_dmds, rhs)
+ = arg_dmds
-- The normal case
| otherwise
@@ -2036,10 +2108,7 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs
-- , text "max" <+> ppr max_wkr_args
-- , text "dmds before:" <+> ppr (map idDemandInfo (filter isId bndrs))
-- , text "dmds after: " <+> ppr arg_dmds' ]) $
- (arg_dmds', set_lam_dmds arg_dmds' rhs)
- -- set_lam_dmds: we must attach the final boxities to the lambda-binders
- -- of the function, both because that's kosher, and because CPR analysis
- -- uses the info on the binders directly.
+ arg_dmds'
where
opts = ae_opts env
(bndrs, _body) = collectBinders rhs
@@ -2047,8 +2116,11 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs
arg_triples :: [(Type, StrictnessMark, Demand)]
arg_triples = take ww_arity $
- [ (idType bndr, NotMarkedStrict, get_dmd bndr)
- | bndr <- bndrs, isRuntimeVar bndr ]
+ zipWith mk_triple
+ [ bndr | bndr <- bndrs, isRuntimeVar bndr ]
+ arg_dmds
+ where
+ mk_triple bndr arg_dmd = (idType bndr, NotMarkedStrict, get_dmd arg_dmd)
arg_dmds' = ww_arg_dmds ++ map trimBoxity (drop ww_arity arg_dmds)
-- If ww_arity < length arg_dmds, the leftover ones
@@ -2064,12 +2136,10 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs
-- This is the budget initialisation step of
-- Note [Worker argument budget]
- get_dmd :: Id -> Demand
- get_dmd bndr
+ get_dmd :: Demand -> Demand
+ get_dmd dmd
| is_bot_fn = unboxDeeplyDmd dmd -- See Note [Boxity for bottoming functions],
| otherwise = dmd -- case (B)
- where
- dmd = idDemandInfo bndr
-- is_bot_fn: see Note [Boxity for bottoming functions]
is_bot_fn = div == botDiv
@@ -2126,19 +2196,6 @@ finaliseArgBoxities env fn ww_arity arg_dmds div rhs
| positiveTopBudget bg_inner' = (bg_inner', dmd')
| otherwise = (bg_inner, trimBoxity dmd)
- set_lam_dmds :: [Demand] -> CoreExpr -> CoreExpr
- -- Attach the demands to the outer lambdas of this expression
- set_lam_dmds (dmd:dmds) (Lam v e)
- | isTyVar v = Lam v (set_lam_dmds (dmd:dmds) e)
- | otherwise = Lam (v `setIdDemandInfo` dmd) (set_lam_dmds dmds e)
- set_lam_dmds dmds (Cast e co) = Cast (set_lam_dmds dmds e) co
- -- This case happens for an OPAQUE function, which may look like
- -- f = (\x y. blah) |> co
- -- We give it strictness but no boxity (#22502)
- set_lam_dmds _ e = e
- -- In the OPAQUE case, the list of demands at this point might be
- -- non-empty, e.g., when looking at a PAP. Hence don't panic (#22997).
-
finaliseLetBoxity
:: AnalEnv
-> Type -- ^ Type of the let-bound Id
=====================================
compiler/GHC/Types/Demand.hs
=====================================
@@ -23,6 +23,8 @@ module GHC.Types.Demand (
lubCard, lubDmd, lubSubDmd,
-- *** Greatest lower bound
glbCard,
+ -- *** Maximum (glb on strictness, lub on usage)
+ maxCard, maxDmd,
-- *** Plus
plusCard, plusDmd, plusSubDmd,
-- *** Multiply
@@ -49,13 +51,13 @@ module GHC.Types.Demand (
-- * Demand environments
DmdEnv(..), addVarDmdEnv, mkTermDmdEnv, nopDmdEnv, plusDmdEnv, plusDmdEnvs,
- multDmdEnv, reuseEnv,
+ lubDmdEnv, multDmdEnv, reuseEnv,
-- * Demand types
DmdType(..), dmdTypeDepth,
-- ** Algebra
nopDmdType, botDmdType,
- lubDmdType, plusDmdType, multDmdType, discardArgDmds,
+ lubDmdType, maxDmdType, plusDmdType, multDmdType, discardArgDmds,
-- ** Other operations
peelFV, findIdDemand, addDemand, splitDmdTy, deferAfterPreciseException,
@@ -864,6 +866,89 @@ lubSubDmd sd1@Poly{} sd2 = lubSubDmd sd2 sd1
-- Otherwise (Call `lub` Prod) return Top
lubSubDmd _ _ = topSubDmd
+{- Note [Combining demands for stable unfoldings]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+When a function has a stable unfolding, the optimised RHS and the unfolding
+may have different demand signatures for the same arguments. This can happen
+because:
+
+ * The optimised RHS may have had transformations applied that reveal
+ strictness (e.g., inlining exposes a case on an argument).
+ Example:
+ RHS: x
+ Unfolding: head [x]
+ It's clear that the RHS is strict in `x`, but the demand analyser won't
+ spot that when it analyses the unfolding.
+
+ * The optimised RHS may have had transformations applied that drop usage
+ (e.g., a rewrite rule fires that doesn't use an argument, or a seq on
+ a dictionary is dropped because dictionaries are known to terminate).
+ Example:
+ RHS: a
+ Unfolding: fst g
+ where `g` is in scope as `g = (a,b)`.
+
+See Note [Absence analysis for stable unfoldings and RULES] in
+GHC.Core.Opt.DmdAnal for the broader context.
+
+When we inline the stable unfolding at a call site, we get the unfolding's
+behaviour, not the RHS's. So we must be conservative and combine the demands:
+
+ * For strictness (lower bounds): we can take the MAXIMUM (glb).
+ If the RHS reveals that an argument is strict, that strictness was
+ always there semantically - the analysis just couldn't see it in the
+ unfolding. Sound optimisations never make lazy code strict.
+
+ * For usage (upper bounds): we must take the MAXIMUM (lub).
+ If the unfolding uses an argument but the RHS doesn't, we must not
+ mark it absent, or we'll replace it with rubbish that the unfolding
+ will then try to use, causing a segfault. See #26416.
+
+So for cardinality bounds [l1..u1] from RHS and [l2..u2] from unfolding,
+we compute [max(l1,l2)..max(u1,u2)].
+-}
+
+-- | Takes the maximum of both the lower and upper bound of two 'Card's.
+-- Semantically, this is glb on lower (strictness) and lub on upper (usage).
+-- See Note [Combining demands for stable unfoldings].
+maxCard :: Card -> Card -> Card
+-- Given Note [Bit vector representation for Card]:
+-- * bit 0 (strictness): take AND (glb) - 0 means strict, so 0 wins
+-- * bits 1,2 (usage): take OR (lub) - if either uses, result uses
+maxCard (Card a) (Card b) = Card ((a .&. b .&. 0b001) .|. ((a .|. b) .&. 0b110))
+
+-- | Takes the maximum of both the lower and upper bounds of two 'Demand's.
+-- Semantically, glb on lower (strictness) and lub on upper (usage).
+-- See Note [Combining demands for stable unfoldings].
+maxDmd :: Demand -> Demand -> Demand
+maxDmd BotDmd dmd2 = dmd2
+maxDmd dmd1 BotDmd = dmd1
+maxDmd (n1 :* sd1) (n2 :* sd2) =
+ maxCard n1 n2 :* maxSubDmd sd1 sd2
+
+maxSubDmd :: SubDemand -> SubDemand -> SubDemand
+-- Shortcuts for neutral and absorbing elements.
+maxSubDmd (Poly Unboxed C_00) sd = sd
+maxSubDmd sd (Poly Unboxed C_00) = sd
+maxSubDmd sd@(Poly Boxed C_1N) _ = sd
+maxSubDmd _ sd@(Poly Boxed C_1N) = sd
+-- Prod
+maxSubDmd (Prod b1 ds1) (Poly b2 n2)
+ | let !d = polyFieldDmd b2 n2
+ = mkProd (lubBoxity b1 b2) (strictMap (maxDmd d) ds1)
+maxSubDmd (Prod b1 ds1) (Prod b2 ds2)
+ | equalLength ds1 ds2
+ = mkProd (lubBoxity b1 b2) (strictZipWith maxDmd ds1 ds2)
+-- Handle Call
+maxSubDmd (Call n1 sd1) (viewCall -> Just (n2, sd2)) =
+ mkCall (maxCard n1 n2) (maxSubDmd sd1 sd2)
+-- Handle Poly
+maxSubDmd (Poly b1 n1) (Poly b2 n2) = Poly (lubBoxity b1 b2) (maxCard n1 n2)
+-- Other Poly case by commutativity
+maxSubDmd sd1@Poly{} sd2 = maxSubDmd sd2 sd1
+-- Otherwise (Call `max` Prod) return Top
+maxSubDmd _ _ = topSubDmd
+
-- | Denotes '+' on 'Demand'.
plusDmd :: Demand -> Demand -> Demand
plusDmd AbsDmd dmd2 = dmd2
@@ -1834,6 +1919,26 @@ lubDmdType d1 d2 = DmdType lub_fv lub_ds
lub_ds = zipWithEqual lubDmd ds1 ds2
lub_fv = lubDmdEnv fv1 fv2
+-- | Combine two 'DmdType's for stable unfolding analysis.
+-- See Note [Combining demands for stable unfoldings].
+maxDmdType :: DmdType -> DmdType -> DmdType
+maxDmdType (DmdType fv1 ds1) (DmdType fv2 ds2)
+ = DmdType combined_fv combined_ds
+ where
+ combined_fv = maxDmdEnv fv1 fv2
+ combined_ds = go ds1 ds2
+ -- If lists have different lengths, keep remaining ds1 (from RHS)
+ go rhs [] = rhs
+ go [] _ = []
+ go (r:rhs) (u:unfs) = maxDmd r u : go rhs unfs
+
+-- | See Note [Combining demands for stable unfoldings].
+maxDmdEnv :: DmdEnv -> DmdEnv -> DmdEnv
+maxDmdEnv (DE fv1 d1) (DE fv2 d2) = DE combined_fv combined_div
+ where
+ combined_fv = plusVarEnv_CD maxDmd fv1 (defaultFvDmd d1) fv2 (defaultFvDmd d2)
+ combined_div = lubDivergence d1 d2
+
discardArgDmds :: DmdType -> DmdEnv
discardArgDmds (DmdType fv _) = fv
=====================================
testsuite/tests/dmdanal/should_compile/T18894.stderr
=====================================
@@ -399,7 +399,8 @@ lvl :: (Int, Int)
lvl = case $wg1 2# of { (# ww, ww #) -> (GHC.Types.I# ww, ww) }
-- RHS size: {terms: 22, types: 16, coercions: 0, joins: 0/0}
-$wh1 [InlPrag=[2]] :: GHC.Prim.Int# -> Int
+$wh1 [InlPrag=[2], Dmd=LC(S,!P(L))]
+ :: GHC.Prim.Int# -> Int
[LclId[StrictWorker([])],
Arity=1,
Str=<1L>,
=====================================
testsuite/tests/dmdanal/should_run/M1.hs
=====================================
@@ -0,0 +1,17 @@
+-- Short module name is essential, or else f doesn't inline
+module M1 where
+{-# INLINABLE [2] f #-}
+f :: Int -> Int -> Float
+f !dummy x = if times dummy 0 x == 1
+ then 3.0 else 4.0
+
+{-# INLINE [0] times #-}
+times :: Int -> Int -> Int -> Int
+times dummy 0 x = x `seq` ( 0 + big dummy )
+times _ a b = a * b
+
+{-# RULES "times" [1] forall dummy x. times dummy 0 x = 0 + big dummy #-}
+
+big :: Int -> Int
+big x = succ . succ . succ . succ . succ . succ . succ . succ . succ $ x
+{-# INLINE big #-}
=====================================
testsuite/tests/dmdanal/should_run/T26416.hs
=====================================
@@ -0,0 +1,3 @@
+module Main where
+import M1 ( f )
+main = print (f 19 12)
=====================================
testsuite/tests/dmdanal/should_run/T26416.stdout
=====================================
@@ -0,0 +1 @@
+4.0
=====================================
testsuite/tests/dmdanal/should_run/all.T
=====================================
@@ -35,3 +35,4 @@ test('T22549', normal, compile_and_run, ['-fdicts-strict -fno-specialise'])
test('T23208', exit_code(1), multimod_compile_and_run, ['T23208_Lib', 'T23208'])
test('T25439', normal, compile_and_run, [''])
test('T26748', normal, compile_and_run, [''])
+test('T26416', [extra_files(['M1.hs'])], multimod_compile_and_run, ['T26416','M1.hs'])
=====================================
testsuite/tests/dmdanal/sigs/T21081.stderr
=====================================
@@ -62,7 +62,7 @@ T21081.g: <ML>
T21081.h: <MP(ML,ML)><1!P(1L)>
T21081.h2: <L><1!P(SL)>
T21081.i: <1L><1L><MP(ML,ML)>
-T21081.j: <1!P(1L,1L)>
+T21081.j: <S!P(1L,1L)>
T21081.myfoldl: <LC(S,C(1,L))><1L><1L>
T21081.snd': <1!P(A,1L)>
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/870243e4f2a24730539f01ee8e3f394…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/870243e4f2a24730539f01ee8e3f394…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/spj-reinstallable-base] More WIP [skip ci]
by Simon Peyton Jones (@simonpj) 13 Mar '26
by Simon Peyton Jones (@simonpj) 13 Mar '26
13 Mar '26
Simon Peyton Jones pushed to branch wip/spj-reinstallable-base at Glasgow Haskell Compiler / GHC
Commits:
13d7132f by Simon Peyton Jones at 2026-03-13T17:44:24+00:00
More WIP [skip ci]
- - - - -
12 changed files:
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Builtin/Names/TH.hs
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Iface/Binary.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Types/Name.hs
- compiler/GHC/Unit/External.hs
Changes:
=====================================
compiler/GHC/Builtin/Names.hs
=====================================
@@ -37,7 +37,8 @@ the big-num package or (for plugins) the ghc package.
It's not necessary to know the uniques for these guys, only their names
-Note [Known-key names]
+Note [Overview of
+Note [Known-key names] <---- OLD VERSION
~~~~~~~~~~~~~~~~~~~~~~
It is *very* important that the compiler gives wired-in things and
things with "known-key" names the correct Uniques wherever they
@@ -189,7 +190,7 @@ wired in ones are defined in GHC.Builtin.Types etc.
basicKnownKeyOccs :: [(OccName, Unique)]
basicKnownKeyOccs
- = [ ("Rational", rationalTyConKey) ]
+ = [ (mkTcOcc "Rational", rationalTyConKey) ]
basicKnownKeyNames :: [Name] -- See Note [Known-key names]
basicKnownKeyNames
=====================================
compiler/GHC/Builtin/Names/TH.hs
=====================================
@@ -8,10 +8,10 @@ module GHC.Builtin.Names.TH where
import GHC.Prelude ()
-oimport GHC.Builtin.Names( mk_known_key_name )
+import GHC.Builtin.Names( mk_known_key_name )
import GHC.Unit.Types
import GHC.Types.Name( Name )
-import GHC.Types.Name.Occurrence( tcName, clsName, dataName, varName, fieldName )
+import GHC.Types.Name.Occurrence( OccName, tcName, clsName, dataName, varName, fieldName )
import GHC.Types.Name.Reader( RdrName, nameRdrName )
import GHC.Types.Unique ( Unique )
import GHC.Builtin.Uniques
=====================================
compiler/GHC/Builtin/Utils.hs
=====================================
@@ -1,4 +1,4 @@
-oo{-
+{-
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-}
@@ -28,7 +28,7 @@ module GHC.Builtin.Utils (
-- if you find yourself wanting to look at it you might consider using
-- 'lookupKnownKeyName' or 'isKnownKeyName'.
knownKeyNames,
- knownKeyOccMap,
+ KnownKeyOccMap, knownKeyOccMap,
-- * Miscellaneous
wiredInIds, ghcPrimIds,
@@ -54,7 +54,7 @@ import GHC.Builtin.PrimOps.Ids
import GHC.Builtin.Types
import GHC.Builtin.Types.Literals ( typeNatTyCons )
import GHC.Builtin.Types.Prim
-import GHC.Builtin.Names.TH ( templateHaskellNames )
+import GHC.Builtin.Names.TH ( templateHaskellNames, templateHaskellOccs )
import GHC.Builtin.Names
import GHC.Core.ConLike ( ConLike(..) )
@@ -205,6 +205,9 @@ isKnownKeyName :: Name -> Bool
isKnownKeyName n =
isJust (knownUniqueName $ nameUnique n) || elemUFM n knownKeysMap
+type KnownKeyOccMap = OccEnv Name
+ -- See Note [Overview of known-key Names]
+
-- | `knownKeyOccMap` maps the OccName of a known-key to its Unique
knownKeyOccMap :: OccEnv Unique
knownKeyOccMap = mkOccEnv (basicKnownKeyOccs ++ templateHaskellOccs)
=====================================
compiler/GHC/Hs/Type.hs
=====================================
@@ -117,7 +117,6 @@ import GHC.Core.Ppr ( pprOccWithTick)
import GHC.Core.Type
import GHC.Core.Multiplicity( pprArrowWithMultiplicity )
import GHC.Hs.Doc
-import GHC.Hs.Lit (pprHsStringLit)
import GHC.Generics (Generic, Generically(..))
import GHC.Types.Basic
import GHC.Types.SrcLoc
=====================================
compiler/GHC/HsToCore/Monad.hs
=====================================
@@ -427,8 +427,8 @@ mkDsEnvs unit_env mod rdr_env type_env fam_inst_env ptc msg_var cc_st_var
dsToIfL :: IfL a -> DsM a
-- Run an Iface action in the Ds monad
dsToIfl iface_action
- = { env <- getGblEnv
- ; setEnvs (ds_if_env env) iface_action }
+ = do { env <- getGblEnv
+ ; setEnvs (ds_if_env env) iface_action }
{-
@@ -561,7 +561,17 @@ dsLookupKnownKey occ
then dsToIfL $
lookupImportedKnownKey occ
else
- do {
+ lookupKnownKeyOcc occ
+ }
+
+dsLookupKnownKeyOcc :: OccName -> DsM TyThing
+-- Look up the known-key OccName in the current top-level GlobalRdrEnv
+-- If we get a unique hit, use it; if not, panic.
+dsLookupKnownKeyOcc occ
+ = do { gbl_rdr_env <- dsGetGlobalRdrEnv
+ ; case lookupGRE gbl_rdr_env (lookupOccName occ SameNameSpace) of
+ [name] -> dsLookupGlobal name
+ gres -> pprPanic "lookupKnownKeyOcc" (ppr occ $$ ppr gres) }
dsLookupKnownKeyTyCon :: Name -> DsM TyCon
dsLookupKnownKeyTyCon name
=====================================
compiler/GHC/HsToCore/Types.hs
=====================================
@@ -60,9 +60,11 @@ data DsGblEnv
= DsGblEnv
{ ds_mod :: Module -- For SCC profiling
, ds_fam_inst_env :: FamInstEnv -- Like tcg_fam_inst_env
- , ds_gbl_rdr_env :: GlobalRdrEnv -- needed only for the following reasons:
- -- - to know what newtype constructors are in scope
- -- - to check whether all members of a COMPLETE pragma are in scope
+ , ds_gbl_rdr_env :: GlobalRdrEnv
+ -- The GlobalRdrEnv is needed for the following reasons:
+ -- - to know what newtype constructors are in scope
+ -- - to check whether all members of a COMPLETE pragma are in scope
+ -- - when looking up know-key names
, ds_name_ppr_ctx :: NamePprCtx
, ds_msgs :: IORef (Messages DsMessage) -- Diagnostic messages
, ds_if_env :: (IfGblEnv, IfLclEnv) -- Used for looking up global,
=====================================
compiler/GHC/Iface/Binary.hs
=====================================
@@ -32,23 +32,29 @@ module GHC.Iface.Binary (
import GHC.Prelude
-import GHC.Builtin.Utils ( isKnownKeyName, lookupKnownKeyName )
-import GHC.Unit
-import GHC.Unit.Module.ModIface
-import GHC.Types.Name
-import GHC.Platform.Profile
-import GHC.Types.Unique.FM
+import GHC.Builtin.Utils ( knownKeyOccMap, isKnownKeyName, lookupKnownKeyName )
+
import GHC.Utils.Panic
import GHC.Utils.Binary as Binary
-import GHC.Data.FastMutInt
-import GHC.Types.Unique
import GHC.Utils.Outputable
-import GHC.Types.Name.Cache
+
+import GHC.Types.Name
+import GHC.Types.Unique.FM
+import GHC.Types.Unique
import GHC.Types.SrcLoc
+import GHC.Types.Name.Cache
+
+import GHC.Unit
+import GHC.Unit.Module.ModIface
+
+import GHC.Platform.Profile
import GHC.Platform
import GHC.Settings.Constants
import GHC.Iface.Type (IfaceType(..), getIfaceType, putIfaceType, ifaceTypeSharedByte)
+import GHC.Data.FastMutInt
+import GHC.Data.Maybe( orElse )
+
import Control.Monad
import Data.Array
import Data.Array.IO
@@ -658,17 +664,18 @@ putSymbolTable bh name_count symtab = do
getSymbolTable :: ReadBinHandle -> NameCache -> IO (SymbolTable Name)
-- Create an array of Names for the symbols and add them to the NameCache
-getSymbolTable bh name_cache = do
+getSymbolTable bh name_cache
= updateNameCache' name_cache $ \cache0 ->
do { sz <- get bh :: IO Int
; mut_arr <- newArray_ (0, sz-1) :: IO (IOArray Int Name)
- ; cache <- foldGet' (fromIntegral sz) bh cache0 deserialise_one
+ ; cache <- foldGet' (fromIntegral sz) bh cache0 (deserialise_one mut_arr)
; arr <- unsafeFreeze mut_arr
- ; return (cache, arr) }
+ ; return (cache, arr) }
where
- deserialise_one :: Word -> (Unit, ModuleName, OccName, Bool)
+ deserialise_one :: (IOArray Int Name)
+ -> Word -> (Unit, ModuleName, OccName, Bool)
-> OrigNameCache -> IO OrigNameCache
- deserialise_one i (uid, mod_name, occ, is_known_key) cache
+ deserialise_one mut_arr i (uid, mod_name, occ, is_known_key) cache
= case lookupOrigNameCache cache mod occ of
Just name
-> do { writeArray mut_arr (fromIntegral i) name
@@ -692,15 +699,8 @@ getSymbolTable bh name_cache = do
serialiseName :: WriteBinHandle -> Name -> UniqFM key (Int,Name) -> IO ()
serialiseName bh name _
- = assertPpr (isExternalName name) (ppr name) $
- put_ bh (moduleUnit mod, moduleName mod, nameOccName name, is_known_key)
- where
- (omod, is_known_key)
- = case name of
- WiredIn mod _ _ -> (mod,False)
- External mod -> (mod,False)
- KnownKey mod -> (mod,True)
- _ -> pprPanic "serialiseName" (ppr name)
+ | (mod, occ, is_known_key) <- extNamePieces name
+ = put_ bh (moduleUnit mod, moduleName mod, occ, is_known_key)
-- Note [Symbol table representation of names]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=====================================
compiler/GHC/Iface/Load.hs
=====================================
@@ -184,17 +184,23 @@ loadKnownKeyOccMap
-- We don't have a KnownKeyOccMap yet, so created it
-- from the interface file for KnownKeyName
- do { iface <- loadSrcInterface (text "lookupImportedKnownKey")
- kNOWN_KEY_NAMES
- NotBoot NoPkgQual
+ do { hsc_env <- getTopEnv
+ ; mb_res <- liftIO $ findImportedModule hsc_env kNOWN_KEY_NAMES NoPkgQual
+ ; iface <- case mb_res of
+ Found _ mod -> loadInterfaceWithException doc mod ImportBySystem
+ _ -> panic "loadKnownKeyOccMap" -- ToDo tidy up
+
; let occ_map :: KnownKeyOccMap
occ_map = mkOccEnv [ (getOccName nm, nm)
- | nm <- availNames (mi_exports iface) ]
+ | avail <- mi_exports iface
+ , nm <- availNames avail ]
-- Record the KnownKeyOccMap in the EPS, so we will find it next time
; updateEps_ (\eps -> eps { eps_known_keys = Just occ_map })
; return occ_map } } }
+ where
+ doc = text "Need interface for KnonwKeyNames"
importDecl :: Name -> IfM lcl (MaybeErr IfaceMessage TyThing)
-- Get the TyThing for this Name from an interface file
=====================================
compiler/GHC/Iface/Type.hs
=====================================
@@ -121,6 +121,21 @@ newtype IfLclName = IfLclName
{ getIfLclName :: LexicalFastString
} deriving (Eq, Ord, Show)
+data IfaceBndr -- Local (non-top-level) binders
+ = IfaceIdBndr {-# UNPACK #-} !IfaceIdBndr
+ | IfaceTvBndr {-# UNPACK #-} !IfaceTvBndr
+ deriving (Eq, Ord)
+
+type IfaceIdBndr = (IfaceType, IfLclName, IfaceType) -- (multiplicity, name, type)
+type IfaceTvBndr = (IfLclName, IfaceKind)
+
+type IfaceLamBndr = (IfaceBndr, IfaceOneShot)
+
+data IfaceOneShot -- See Note [Preserve OneShotInfo] in "GHC.Core.Tidy"
+ = IfaceNoOneShot -- and Note [oneShot magic] in "GHC.Types.Id.Make"
+ | IfaceOneShot
+
+
ifLclNameFS :: IfLclName -> FastString
ifLclNameFS = getLexicalFastString . getIfLclName
@@ -141,12 +156,6 @@ ifaceBndrType :: IfaceBndr -> IfaceType
ifaceBndrType (IfaceIdBndr (_, _, t)) = t
ifaceBndrType (IfaceTvBndr (_, t)) = t
-type IfaceLamBndr = (IfaceBndr, IfaceOneShot)
-
-data IfaceOneShot -- See Note [Preserve OneShotInfo] in "GHC.Core.Tidy"
- = IfaceNoOneShot -- and Note [oneShot magic] in "GHC.Types.Id.Make"
- | IfaceOneShot
-
instance Outputable IfaceOneShot where
ppr IfaceNoOneShot = text "NoOneShotInfo"
ppr IfaceOneShot = text "OneShot"
=====================================
compiler/GHC/IfaceToCore.hs
=====================================
@@ -23,7 +23,6 @@ module GHC.IfaceToCore (
tcIfaceAnnotations, tcIfaceCompleteMatches,
tcIfaceExpr, -- Desired by HERMIT (#7683)
tcIfaceGlobal,
- tcifaceKnownKey,
tcIfaceOneShot, tcTopIfaceBindings,
tcIfaceImport,
hydrateCgBreakInfo
@@ -2037,9 +2036,6 @@ tcIfaceOneShot IfaceOneShot = OneShotLam
************************************************************************
-}
-tcIfaceKnownKey :: OcName -> IfL TyThing
-tcIfaceKownKey
-
tcIfaceGlobal :: Name -> IfL TyThing
tcIfaceGlobal name
| Just thing <- wiredInNameTyThing_maybe name
=====================================
compiler/GHC/Types/Name.hs
=====================================
@@ -51,7 +51,7 @@ module GHC.Types.Name (
-- ** Manipulating and deconstructing 'Name's
nameUnique, setNameUnique,
- nameOccName, nameNameSpace, nameModule, nameModule_maybe,
+ nameOccName, nameNameSpace, nameModule, nameModule_maybe, extNamePieces,
setNameLoc,
tidyNameOcc,
localiseName,
@@ -317,10 +317,6 @@ isWiredIn = isWiredInName . getName
isKnownKey :: NamedThing thing => thing -> Bool
isKnownKey = isKnownKeyName' . getName
-knownKeyTyThing_maybe :: Name -> Maybe TyThing
-knownKeyTyThing_maybe (Name {n_sort = KnownKey m}) = Just m
-knownKeyTyThing_maybe _ = Nothing
-
wiredInNameTyThing_maybe :: Name -> Maybe TyThing
wiredInNameTyThing_maybe (Name {n_sort = WiredIn _ thing _}) = Just thing
wiredInNameTyThing_maybe _ = Nothing
@@ -390,10 +386,17 @@ nameModule name =
nameModule_maybe :: Name -> Maybe Module
nameModule_maybe (Name { n_sort = External mod}) = Just mod
-nameModule_maybe (Name { n_nort = KnownKey mod}) = Just mod
+nameModule_maybe (Name { n_sort = KnownKey mod}) = Just mod
nameModule_maybe (Name { n_sort = WiredIn mod _ _}) = Just mod
nameModule_maybe _ = Nothing
+extNamePieces :: Name -> (Module, OccName, Bool)
+-- Get the pieces of an external name, ready to serialise
+extNamePieces (Name { n_occ = occ, n_sort = External mod}) = (mod, occ, False)
+extNamePieces (Name { n_occ = occ, n_sort = WiredIn mod _ _}) = (mod, occ, False)
+extNamePieces (Name { n_occ = occ, n_sort = KnownKey mod}) = (mod, occ, True)
+extNamePieces name = pprPanic "extNamePieces" (ppr name)
+
is_interactive_or_from :: Module -> Module -> Bool
is_interactive_or_from from mod = from == mod || isInteractiveModule mod
@@ -558,17 +561,8 @@ mkExternalName uniq mod occ loc
= Name { n_uniq = uniq, n_sort = External mod,
n_occ = occ, n_loc = loc }
-mkExternalName :: Unique -> Module -> OccName -> SrcSpan -> Name
-{-# INLINE mkExternalName #-}
--- WATCH OUT! External Names should be in the Name Cache
--- (see Note [The Name Cache] in GHC.Iface.Env), so don't just call mkExternalName
--- with some fresh unique without populating the Name Cache
-mkExternalName uniq mod occ loc
- = Name { n_uniq = uniq, n_sort = External mod,
- n_occ = occ, n_loc = loc }
-
mkKnownKeyName :: Unique -> Module -> OccName -> SrcSpan -> Name
-{-# INLINE mkKnonwKeyName #-}
+{-# INLINE mkKnownKeyName #-}
mkKnownKeyName uniq mod occ loc
= Name { n_uniq = uniq, n_sort = KnownKey mod,
n_occ = occ, n_loc = loc }
@@ -647,7 +641,7 @@ stableNameCmp (Name { n_sort = s1, n_occ = occ1 })
sort_cmp (External {}) _ = LT
sort_cmp (KnownKey {}) (External {}) = GT
- sort_cmp (KnownKey m1) (External m2) = m1 `stableModuleCmp` m2
+ sort_cmp (KnownKey m1) (KnownKey m2) = m1 `stableModuleCmp` m2
sort_cmp (KnownKey {}) _ = LT
sort_cmp (WiredIn {}) (External {}) = GT
=====================================
compiler/GHC/Unit/External.hs
=====================================
@@ -21,6 +21,8 @@ import GHC.Prelude
import GHC.Unit
import GHC.Unit.Module.ModIface
+import GHC.Builtin.Utils( KnownKeyOccMap)
+
import GHC.Core.FamInstEnv
import GHC.Core.InstEnv ( InstEnv, emptyInstEnv )
import GHC.Core.Opt.ConstantFold
@@ -48,9 +50,6 @@ type PackageCompleteMatches = CompleteMatches
type PackageIfaceTable = ModuleEnv ModIface
-- Domain = modules in the imported packages
-type KnownKeyOccMap = OccEnv Name
- -- See Note [Overview of KnownKeyNames]
-
-- | Constructs an empty PackageIfaceTable
emptyPackageIfaceTable :: PackageIfaceTable
emptyPackageIfaceTable = emptyModuleEnv
@@ -80,6 +79,7 @@ initExternalPackageState = EPS
, eps_rule_base = mkRuleBase builtinRules
, -- Initialise the EPS rule pool with the built-in rules
eps_mod_fam_inst_env = emptyModuleEnv
+ , eps_known_keys = Nothing
, eps_complete_matches = []
, eps_ann_env = emptyAnnEnv
, eps_stats = EpsStats
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/13d7132f7e424077af9bd90f8081cb1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/13d7132f7e424077af9bd90f8081cb1…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
13 Mar '26
Magnus pushed new branch wip/mangoiv/fallback-nix-darwin at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/mangoiv/fallback-nix-darwin
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26548] 91 commits: ci: remove unused hlint-ghc-and-base job definition
by Simon Peyton Jones (@simonpj) 13 Mar '26
by Simon Peyton Jones (@simonpj) 13 Mar '26
13 Mar '26
Simon Peyton Jones pushed to branch wip/T26548 at Glasgow Haskell Compiler / GHC
Commits:
4157160f by Cheng Shao at 2026-02-13T06:27:04-05:00
ci: remove unused hlint-ghc-and-base job definition
This patch removes the unused `hlint-ghc-and-base` job definition,
it's never run since !9806. Note that hadrian lint rules still work
locally, so anyone that wishes to run hlint on the codebase can
continue to do so in their local worktree.
- - - - -
039f1977 by Cheng Shao at 2026-02-13T06:27:47-05:00
wasm: use import.meta.main for proper distinction of nodejs main modules
This patch uses `import.meta.main` for proper distinction of nodejs
main modules, especially when the main module might be installed as a
symlink. Fixes #26916.
- - - - -
14f485ee by ARATA Mizuki at 2026-02-17T09:09:24+09:00
Support more x86 extensions: AVX-512 {BW,DQ,VL} and GFNI
Also, mark AVX-512 ER and PF as deprecated.
AVX-512 instructions can be used for certain 64-bit integer vector operations.
GFNI can be used to implement bitReverse (currently not used by NCG, but LLVM may use it).
Closes #26406
Addresses #26509
- - - - -
016f79d5 by fendor at 2026-02-17T09:16:16-05:00
Hide implementation details from base exception stack traces
Ensure we hide the implementation details of the exception throwing mechanisms:
* `undefined`
* `throwSTM`
* `throw`
* `throwIO`
* `error`
The `HasCallStackBacktrace` should always have a length of exactly 1,
not showing internal implementation details in the stack trace, as these
are vastly distracting to end users.
CLC proposal [#387](https://github.com/haskell/core-libraries-committee/issues/387)
- - - - -
4f2840f2 by Brian J. Cardiff at 2026-02-17T17:04:08-05:00
configure: Accept happy-2.2
In Jan 2026 happy-2.2 was released. The most sensible change is https://github.com/haskell/happy/issues/335 which didn't trigger in a fresh build
- - - - -
10b4d364 by Duncan Coutts at 2026-02-17T17:04:52-05:00
Fix errors in the documentation of the eventlog STOP_THREAD status codes
Fix the code for BlockedOnMsgThrowTo.
Document all the known historical warts.
Fixes issue #26867
- - - - -
c5e15b8b by Phil de Joux at 2026-02-18T05:07:36-05:00
haddock: use snippets for all list examples
- generate snippet output for docs
- reduce font size to better fit snippets
- Use only directive to guard html snippets
- Add latex snippets for lists
- - - - -
d388bac1 by Phil de Joux at 2026-02-18T05:07:36-05:00
haddock: Place the snippet input and output together
- Put the output seemingly inside the example box
- - - - -
016fa306 by Samuel Thibault at 2026-02-18T05:08:35-05:00
Fix linking against libm by moving the -lm option
For those systems that need -lm for getting math functions, this is
currently added on the link line very early, before the object files being
linked together. Newer toolchains enable --as-needed by default, which means
-lm is ignored at that point because no object requires a math function
yet. With such toolchains, we thus have to add -lm after the objects, so the
linker actually includes libm in the link.
- - - - -
68bd0805 by Teo Camarasu at 2026-02-18T05:09:19-05:00
ghc-internal: Move GHC.Internal.Data.Bool to base
This is a tiny module that only defines bool :: Bool -> a -> a -> a. We can just move this to base and delete it from ghc-internal. If we want this functionality there we can just use a case statement or if-then expression.
Resolves 26865
- - - - -
4c40df3d by fendor at 2026-02-20T10:24:48-05:00
Add optional `SrcLoc` to `StackAnnotation` class
`StackAnnotation`s give access to an optional `SrcLoc` field that
user-added stack annotations can use to provide better backtraces in both error
messages and when decoding the callstack.
We update builtin stack annotations such as `StringAnnotation` and
`ShowAnnotation` to also capture the `SrcLoc` of the current `CallStack`
to improve backtraces by default (if stack annotations are used).
This change is backwards compatible with GHC 9.14.1.
- - - - -
fd9aaa28 by Simon Hengel at 2026-02-20T10:25:33-05:00
docs: Fix grammar in explicit_namespaces.rst
- - - - -
44354255 by Vo Minh Thu at 2026-02-20T18:53:06-05:00
GHCi: add a :version command.
This looks like:
ghci> :version
GHCi, version 9.11.20240322
This closes #24576.
Co-Author: Markus Läll <markus.l2ll(a)gmail.com>
- - - - -
eab3dbba by Andreas Klebinger at 2026-02-20T18:53:51-05:00
hadrian/build-cabal: Better respect and utilize -j
* We now respect -j<n> for the cabal invocation to build hadrian rather
than hardcoding -j
* We use the --semaphore flag to ensure cabal/ghc build the hadrian
executable in parallel using the -jsem mechanism.
Saves 10-15s on fresh builds for me.
Fixes #26876
- - - - -
17839248 by Teo Camarasu at 2026-02-24T08:36:03-05:00
ghc-internal: avoid depending on GHC.Internal.Control.Monad.Fix
This module contains the definition of MonadFix, since we want an
instance for IO, that instance requires a lot of machinery and we want
to avoid an orphan instance, this will naturally be quite high up in the
dependency graph.
So we want to avoid other modules depending on it as far as possible.
On Windows, the IO manager depends on the RTSFlags type, which
transtively depends on MonadFix. We refactor things to avoid this
dependency, which would have caused a regression.
Resolves #26875
Metric Decrease:
T12227
- - - - -
fa88d09a by Wolfgang Jeltsch at 2026-02-24T08:36:47-05:00
Refine the imports of `System.IO.OS`
Commit 68bd08055594b8cbf6148a72d108786deb6c12a1 replaced the
`GHC.Internal.Data.Bool` import by a `GHC.Internal.Base` import.
However, while the `GHC.Internal.Data.Bool` import was conditional and
partial, the `GHC.Internal.Base` import is unconditional and total. As a
result, the import list is not tuned to import only the necessary bits
anymore, and furthermore GHC emits a lot of warnings about redundant
imports.
This commit makes the `GHC.Internal.Base` import conditional and partial
in the same way that the `GHC.Internal.Data.Bool` import was.
- - - - -
c951fef1 by Cheng Shao at 2026-02-25T20:58:28+00:00
wasm: add /assets endpoint to serve user-specified assets
This patch adds an `/assets` endpoint to the wasm dyld http server, so
that users can also fetch assets from the same host with sensible
default MIME types, without needing a separate http server for assets
that also introduces CORS headaches:
- A `-fghci-browser-assets-dir` driver flag is added to specify the
assets root directory (defaults to `$PWD`)
- The dyld http server fetches `mime-db` on demand and uses it as
source of truth for mime types.
Closes #26951.
- - - - -
dde22f97 by Sylvain Henry at 2026-02-26T13:14:03-05:00
Fix -fcheck-prim-bounds for non constant args (#26958)
Previously we were only checking bounds for constant (literal)
arguments!
I've refactored the code to simplify the generation of out-of-line Cmm
code for the primop composed of some inline code + some call to an
external Cmm function.
- - - - -
bd3eba86 by Vladislav Zavialov at 2026-02-27T05:48:01-05:00
Check for negative type literals in the type checker (#26861)
GHC disallows negative type literals (e.g., -1), as tested by T8306 and
T8412. This check is currently performed in the renamer:
rnHsTyLit tyLit@(HsNumTy x i) = do
when (i < 0) $
addErr $ TcRnNegativeNumTypeLiteral tyLit
However, this check can be bypassed using RequiredTypeArguments
(see the new test case T26861). Prior to this patch, such programs
caused the compiler to hang instead of reporting a proper error.
This patch addresses the issue by adding an equivalent check in
the type checker, namely in tcHsType.
The diff is deliberately minimal to facilitate backporting. A more
comprehensive rework of HsTyLit is planned for a separate commit.
- - - - -
faf14e0c by Vladislav Zavialov at 2026-02-27T05:48:45-05:00
Consistent pretty-printing of HsString, HsIsString, HsStrTy
Factor out a helper to pretty-print string literals, thus fixing newline
handling for overloaded string literals and type literals.
Test cases: T26860ppr T26860ppr_overloaded T26860ppr_tylit
Follow up to ddf1434ff9bb08cfef3c93f23de6b83ec698aa27
- - - - -
f108a972 by Arnaud Spiwack at 2026-02-27T12:53:01-05:00
Make list comprehension completely non-linear
Fixes #25081
From the note:
The usefulness of list comprehension in conjunction with linear types is dubious.
After all, statements are made to be run many times, for instance in
```haskell
[u | y <- [0,1], stmts]
```
both `u` and `stmts` are going to be run several times.
In principle, though, there are some position in a monad comprehension
expression which could be considered linear. We could try and make it so that
these positions are considered linear by the typechecker, but in practice the
desugarer doesn't take enough care to ensure that these are indeed desugared to
linear sites. We tried in the past, and it turned out that we'd miss a
desugaring corner case (#25772).
Until there's a demand for this very specific improvement, let's instead be
conservative, and consider list comprehension to be completely non-linear.
- - - - -
ae799cab by Simon Jakobi at 2026-02-27T12:53:54-05:00
PmAltConSet: Use Data.Set instead of Data.Map
...to store `PmLit`s.
The Map was only used to map keys to themselves.
Changing the Map to a Set saves a Word of memory per entry.
Resolves #26756.
- - - - -
dcd7819c by Vladislav Zavialov at 2026-02-27T18:46:03-05:00
Drop HsTyLit in favor of HsLit (#26862, #25121)
This patch is a small step towards unification of HsExpr and HsType,
taking care of literals (HsLit) and type literals (HsTyLit).
Additionally, it improves error messages for unsupported type literals,
such as unboxed or fractional literals (test cases: T26862, T26862_th).
Changes to the AST:
* Use HsLit where HsTyLit was previously used
* Use HsChar where HsCharTy was previously used
* Use HsString where HsStrTy was previously used
* Use HsNatural (NEW) where HsNumTy was previously used
* Use HsDouble (NEW) to represent unsupported fractional type literals
Changes to logic:
* Parse unboxed and fractional type literals (to be rejected later)
* Drop the check for negative literals in the renamer (rnHsTyLit)
in favor of checking in the type checker (tc_hs_lit_ty)
* Check for invalid type literals in TH (repTyLit) and report
unrepresentable literals with ThUnsupportedTyLit
* Allow negative type literals in TH (numTyLit). This is fine as
these will be taken care of at splice time (test case: T8306_th)
- - - - -
c927954f by Vladislav Zavialov at 2026-02-27T18:46:50-05:00
Increase test coverage of diagnostics
Add test cases for the previously untested diagnostics:
[GHC-01239] PsErrIfInFunAppExpr
[GHC-04807] PsErrProcInFunAppExpr
[GHC-08195] PsErrInvalidRecordCon
[GHC-16863] PsErrUnsupportedBoxedSumPat
[GHC-18910] PsErrSemiColonsInCondCmd
[GHC-24737] PsErrInvalidWhereBindInPatSynDecl
[GHC-25037] PsErrCaseInFunAppExpr
[GHC-25078] PsErrPrecedenceOutOfRange
[GHC-28021] PsErrRecordSyntaxInPatSynDecl
[GHC-35827] TcRnNonOverloadedSpecialisePragma
[GHC-40845] PsErrUnpackDataCon
[GHC-45106] PsErrInvalidInfixHole
[GHC-50396] PsErrInvalidRuleActivationMarker
[GHC-63930] MultiWayIfWithoutAlts
[GHC-65536] PsErrNoSingleWhereBindInPatSynDecl
[GHC-67630] PsErrMDoInFunAppExpr
[GHC-70526] PsErrLetCmdInFunAppCmd
[GHC-77808] PsErrDoCmdInFunAppCmd
[GHC-86934] ClassPE
[GHC-90355] PsErrLetInFunAppExpr
[GHC-91745] CasesExprWithoutAlts
[GHC-92971] PsErrCaseCmdInFunAppCmd
[GHC-95644] PsErrBangPatWithoutSpace
[GHC-97005] PsErrIfCmdInFunAppCmd
Remove unused error constructors:
[GHC-44524] PsErrExpectedHyphen
[GHC-91382] TcRnIllegalKindSignature
- - - - -
3a9470fd by Torsten Schmits at 2026-02-27T18:47:34-05:00
Avoid expensive computation for debug logging in `mergeDatabases` when log level is low
This computed and traversed a set intersection for every single
dependency unconditionally.
- - - - -
ea4c2cbd by Brandon Chinn at 2026-02-27T16:22:38-08:00
Implement QualifiedStrings (#26503)
See Note [Implementation of QualifiedStrings]
- - - - -
08bc245b by sheaf at 2026-03-01T11:11:54-05:00
Clean up join points, casts & ticks
This commit shores up the logic dealing with casts and ticks occurring
in between a join point binding and a jump.
Fixes #26642 #26929 #26693
Makes progress on #14610 #26157 #26422
Changes:
- Remove 'GHC.Types.Tickish.TickishScoping' in favour of simpler
predicates 'tickishHasNoScope'/'tickishHasSoftScope', as things were
before commit 993975d3. This makes the code easier to read and
document (fewer indirections).
- Introduce 'canCollectArgsThroughTick' for consistent handling of
ticks around PrimOps and other 'Id's that cannot be eta-reduced.
See overhauled Note [Ticks and mandatory eta expansion].
- New Note [JoinId vs TailCallInfo] in GHC.Core.SimpleOpt that explains
robustness of JoinId vs fragility of TailCallInfo.
- Allow casts/non-soft-scoped ticks to occur in between a join point
binder and a jump, but only in Core Prep.
See Note [Join points, casts, and ticks] and
Note [Join points, casts, and ticks... in Core Prep]
in GHC.Core.Opt.Simplify.Iteration.
Also update Core Lint to account for this.
See Note [Linting join points with casts or ticks] in GHC.Core.Lint.
- Update 'GHC.Core.Utils.mergeCaseAlts' to avoid pushing a cast in
between a join point binding and its jumps. This fixes #26642.
See the new (MC5) and (MC6) in Note [Merge Nested Cases].
- Update float out to properly handle source note ticks. They are now
properly floated out instead of being discarded.
This increases the number of ticks in certain tests with -g.
Test cases: T26642 and TrickyJoins.
Metric increase due to more source note ticks with -g:
-------------------------
Metric Increase:
libdir
size_hello_artifact
size_hello_unicode
-------------------------
- - - - -
476c4cdf by Sean D. Gillespie at 2026-03-02T10:14:37-05:00
Add SIMD absolute value on x86 and LLVM
On x86, absolute value of 32 bits or less is implemented with
PABSB/PABSW/PABSD if SSSE3 is available. Otherwise, there is a fallback
for SSE2. For 64 bit integers it uses VPABSQ, required by AVX-512VL,
with fallbacks for SSE4.2 and SSE2.
There is no dedicated instruction for floating point absolute value on
x86, so it is simulated using bitwise AND.
Absolute value for signed integers and floats are implemented by the
"llvm.abs/llvm.fabs" standard library intrinsics. This implementation
uses MachOps constructors, unlike non-vector floating point absolute
value, which uses CallishMachOps.
- - - - -
709448c0 by Sean D. Gillespie at 2026-03-02T10:14:46-05:00
Add SIMD floating point square root
On x86, this is implemented with the SQRTPS and SQRTPD instructions. On
LLVM, it uses the sqrt library intrinstic.
- - - - -
0deadf66 by Sean D. Gillespie at 2026-03-02T10:14:47-05:00
Improve error message for SIMD on aarch64
When encountering vector literals on aarch64, previously it would
throw:
<no location info>: error:
panic! (the 'impossible' happened)
GHC version 9.15.20251219:
getRegister' (CmmLit:CmmVec):
Now it is more consistent with the other vector operations:
<no location info>: error:
sorry! (unimplemented feature or known bug)
GHC version 9.15.20251219:
SIMD operations on AArch64 currently require the LLVM backend
- - - - -
7d64031b by Vladislav Zavialov at 2026-03-03T11:09:28-05:00
Replace maybeAddSpace with spaceIfSingleQuote
Simplify pretty-printing of HsTypes by using spaceIfSingleQuote.
This allows us to drop the unwieldy lhsTypeHasLeadingPromotionQuote
helper function.
Follow-up to 178c1fd830c78377ef5d338406a41e1d8eb5f0da
- - - - -
598db847 by Wolfgang Jeltsch at 2026-03-06T06:25:25-05:00
Correct `hIsReadable` and `hIsWritable` for duplex handles
This contribution implements CLC proposal #371. It changes `hIsReadable`
and `hIsWritable` such that they always throw a respective exception
when encountering a closed or semi-closed handle, not just in the case
of a file handle.
- - - - -
b90201e5 by Wolfgang Jeltsch at 2026-03-06T06:25:25-05:00
Document `SemiClosedHandle`
- - - - -
c9df72b5 by Wolfgang Jeltsch at 2026-03-06T06:25:25-05:00
Tell users what “semi-closed” means for duplex handles
- - - - -
a8aa1868 by Ilias Tsitsimpis at 2026-03-06T06:26:29-05:00
Fix determinism of linker arguments
The switch from Data.Map to UniqMap in 3b5be05ac29 introduced
non-determinism in the order of packages passed to the linker.
This resulted in non-reproducible builds where the DT_NEEDED entries in
dynamic libraries were ordered differently across builds.
Fix the regression by explicitly sorting the package list derived from
UniqMap.
Fixes #26838
- - - - -
9b64ad3a by Matthew Pickering at 2026-03-06T06:27:16-05:00
determinism: Use a deterministic renaming when writing bytecode files
Now when writing the bytecode file, a counter and substitution are used
to provide deterministic keys to local variables (rather than relying on
uniques). This change ensures that `.gbc` are produced
deterministically.
Fixes #26499
- - - - -
d29800e0 by Teo Camarasu at 2026-03-06T06:28:46-05:00
ghc-internal: delete Version hs-boot loop
Version has a Read instance which needs Unicode but part of the Unicode interface is the unicode version. This is easy to resolve. We simply don't re-export the version from the Unicode module.
Resolves #26940
- - - - -
ad25af90 by Sylvain Henry at 2026-03-06T06:30:33-05:00
Linker: implement support for COMMON symbols (#6107)
Add some support for COMMON symbols. We don't support common symbols
having different sizes where the larger one is allocated after the
smaller one. The linker will fail with an appropriate error message if
it happens.
- - - - -
3b59f158 by Cheng Shao at 2026-03-06T06:31:16-05:00
compiler: fix redundant import of GHC.Hs.Lit
This patch removes a redundant import of `GHC.Hs.Lit` which causes a
ghc build failure with validate flavours when bootstrapping from 9.14.
Fixes #26972.
- - - - -
148d36f3 by Cheng Shao at 2026-03-06T06:32:01-05:00
compiler: avoid unneeded traversals in GHC.Unit.State
Following !15591, this patch avoids unneeded traversals in
`reportCycles`/`reportUnusable` when log verbosity is below given
threshold. Also applies `logVerbAtLeast` when appropriate.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
7e31367c by Cheng Shao at 2026-03-06T06:32:46-05:00
ghc-internal: fix redundant import in GHC.Internal.Event.Windows.ManagedThreadPool
This patch fixes redundant import in
`GHC.Internal.Event.Windows.ManagedThreadPool` that causes a
compilation error when building windows target with validate flavours
and bootstrapping from 9.14. Fixes #26976.
- - - - -
fc8b8e27 by sheaf at 2026-03-06T06:33:28-05:00
System.Info.fullCompilerVersion: add 'since' annot
Fixes #26973
- - - - -
c8238375 by Sylvain Henry at 2026-03-06T06:34:23-05:00
Hadrian: deprecate --bignum and automatically enable +native_bignum for JS
Deprecate --bignum=... to select the bignum backend. It's only used to
select the native backend, and this can be done with the +native_bignum
flavour transformer.
Additionally, we automatically enable +native_bignum for the JS target
because the GMP backend isn't supported.
- - - - -
a3ac7074 by Sylvain Henry at 2026-03-06T06:35:17-05:00
JS: fix putEnum/fromEnum (#24593)
Don't go through Word16 when serializing Enums.
- - - - -
0b36e96c by Andreas Klebinger at 2026-03-06T06:35:58-05:00
Docs: Document -fworker-wrapper-cbv default setting.
Fixes #26841
- - - - -
eca445e7 by mangoiv at 2026-03-07T05:02:36-05:00
drop deb9/10 from CI, add deb13
debian 9 and 10 are end of life, hence we drop them
from our CI, but we do add debian 13. Jobs that were
previously run on 9 and 10 run on 13, too, jobs that
were run on 10, are run on 11 now. Jobs that were
previously run on debian 12 are run on debian 13 now.
This MR also updates hadrian's bootstrap plans for that
reason.
Metric Decrease:
T9872d
- - - - -
12f8b829 by Luite Stegeman at 2026-03-07T05:03:33-05:00
Fix GHC.Internal.Prim haddock
Haddock used to parse Haskell source to generate documentation,
but switched to using interface files instead. This broke documentation
of the GHC.Internal.Prim module, since it's a wired-in interface that
didn't provide a document structure.
This patch adds the missing document structure and updates genprimopcode
to make the section headers and descriptions available.
fixes #26954
- - - - -
f87e5e57 by Luite Stegeman at 2026-03-07T05:03:33-05:00
Remove obsolete --make-haskell-source from genprimopcode
Now that haddock uses the wired-in interface for GHC.Internal.Prim,
the generated Haskell source file is no longer needed. Remove the
--make-haskell-source code generator from genprimopcode and replace
the generated GHC/Internal/Prim.hs with a minimal static source file.
- - - - -
4a7ddc7b by Sylvain Henry at 2026-03-07T05:04:59-05:00
JS: fix linking of exposed but non-preload units (#24886)
Units exposed in the unit database but not explicitly passed on the
command-line were not considered by the JS linker. This isn't an issue
for cabal which passes every unit explicitly but it is an issue when
using GHC directly (cf T24886 test).
- - - - -
689aafcd by mangoiv at 2026-03-07T05:05:52-05:00
testsuite: double foundation timeout multiplier
The runtime timeout in the foundation test was regularly hit by code
generated by the wasm backend - we increase the timout since the high
runtime is expected on the wasm backend for this rather complex test.
Resolves #26938
- - - - -
a46a1bb1 by Cheng Shao at 2026-03-09T04:50:30-04:00
compiler: add myCapabilityExpr to GHC.Cmm.Utils
This commit adds `myCapabilityExpr` to `GHC.Cmm.Utils` which is
computed from `BaseReg`. It's convenient for codegen logic where one
needs to pass the current Capability's pointer.
- - - - -
4afc65b1 by Cheng Shao at 2026-03-09T04:50:30-04:00
compiler: lower tryPutMVar# into a ccall directly
This patch addresses an old TODO of `stg_tryPutMVarzh` by removing it
completely and making the compiler lower `tryPutMVar#` into a ccall to
`performTryPutMVar` directly, without landing into an intermediate C
or Cmm function. `performTryPutMVar` is promoted to a public RTS
function with default visibility, and the compiler lowering logic
takes into account the C ABI of `performTryPutMVar` and converts from
C Bool to primop's `Int#` result properly.
- - - - -
9e3d6a58 by Simon Hengel at 2026-03-09T04:51:15-04:00
Don't use #line in haddocks
This confuses the parser. Haddock output is unaffected by this change.
(read: this still produces the same documentation)
- - - - -
f4e8fec2 by Wolfgang Jeltsch at 2026-03-09T04:52:01-04:00
Remove in-package dependencies on `GHC.Internal.System.IO`
This contribution eliminates all dependencies on
`GHC.Internal.System.IO` from within `ghc-internal`. It comprises the
following changes:
* Make `GHC.Internal.Fingerprint` independent of I/O support
* Tighten the dependencies of `GHC.Internal.Data.Version`
* Tighten the dependencies of `GHC.Internal.TH.Monad`
* Tighten the dependencies of `GHCi.Helpers`
* Move some code that needs `System.IO` to `template-haskell`
* Move the `GHC.ResponseFile` implementation into `base`
* Move the `System.Exit` implementation into `base`
* Move the `System.IO.OS` implementation into `base`
Metric Decrease:
size_hello_artifact
size_hello_artifact_gzip
size_hello_unicode
size_hello_unicode_gzip
- - - - -
91df4c82 by Sylvain Henry at 2026-03-09T04:53:20-04:00
T18832: fix Windows CI failure by dropping removeDirectoryRecursive
On Windows, open file handles prevent deletion. After killThread, the
closer thread may not have called hClose yet, causing removeDirectoryRecursive
to fail with "permission denied". The test harness cleans up the run
directory anyway, so the call is redundant.
- - - - -
d7fe9671 by Cheng Shao at 2026-03-09T04:54:04-04:00
compiler: fix redundant import in GHC.StgToJS.Object
This patch fixes a redundant import in GHC.StgToJS.Object that causes
a build failure when compiling head from 9.14 with validate flavours.
Fixes #26991.
- - - - -
0bfd29c3 by Cheng Shao at 2026-03-09T04:54:46-04:00
wasm: fix `Illegal foreign declaration` failure when ghci loads modules with JSFFI exports
This patch fixes a wasm ghci error when loading modules with JSFFI
exports; the `backendValidityOfCExport` check in `tcCheckFEType`
should only makes sense and should be performed when not checking the
JavaScript calling convention; otherwise, when the calling convention
is JavaScript, the codegen logic should be trusted to backends that
actually make use of it. Fixes #26998.
- - - - -
e659610c by Duncan Coutts at 2026-03-09T12:08:35-04:00
Apply NOINLINE pragmas to generated Typeable bindings
For context, see the existing Note [Grand plan for Typeable]
and the Note [NOINLINE on generated Typeable bindings] added in the
subsequent commit.
This is about reducing the number of exported top level names and
unfoldings, which reduces interface file sizes and reduces the number of
global/dynamic linker symbols.
Also accept the changed test output and metric decreases.
Tests that record the phase output for type checking or for simplifier
end up with different output: the generated bindings now have an
Inline [~] annotation, and many top level names are now local rather
than module-prefixed for export.
Also accept the numerous metric decreases in compile_time/bytes
allocated, and a few in compile_time/max_bytes_used.
There's also one instance of a decrease in runtime/max_bytes_used but
it's a ghci-way test and so presumably the reason is that it loads
smaller .hi files and/or links fewer symbols.
-------------------------
Metric Decrease:
CoOpt_Singletons
MultiLayerModulesTH_OneShot
MultilineStringsPerf
T10421
T10547
T12150
T12227
T12234
T12425
T13035
T13056
T13253
T13253-spj
T15304
T15703
T16875
T17836b
T17977b
T18140
T18223
T18282
T18304
T18698a
T18698b
T18730
T18923
T20049
T21839c
T24471
T24582
T24984
T3064
T4029
T5030
T5642
T5837
T6048
T9020
T9198
T9961
TcPlugin_RewritePerf
WWRec
hard_hole_fits
mhu-perf
-------------------------
- - - - -
67df5161 by Duncan Coutts at 2026-03-09T12:08:35-04:00
Add documentation Note [NOINLINE on generated Typeable bindings]
and refer to it from the code and existing documentation.
- - - - -
c4ad6167 by Duncan Coutts at 2026-03-09T12:08:35-04:00
Switch existing note to "named wrinkle" style, (GPT1)..(GPT7)
GPT = Grand plan for Typeable
- - - - -
dc84f8e2 by Cheng Shao at 2026-03-09T12:09:21-04:00
ci: only build deb13 for validate pipeline aarch64-linux jobs
This patch drops the redundant aarch64-linux deb12 job from validate pipelines
and only keeps deb13; it's still built in nightly/release pipelines. Closes #27004.
- - - - -
23a50772 by Rajkumar Natarajan at 2026-03-10T14:11:37-04:00
chore: Merge GHC.Internal.TH.Quote into GHC.Internal.TH.Monad
Move the QuasiQuoter datatype from GHC.Internal.TH.Quote to
GHC.Internal.TH.Monad and delete the Quote module.
Update submodule template-haskell-quasiquoter to use the merged
upstream version that imports from the correct module.
Co-authored-by: Cursor <cursoragent(a)cursor.com>
- - - - -
a2bb6fc3 by Simon Jakobi at 2026-03-10T14:12:23-04:00
Add regression test for #16122
- - - - -
604e1180 by Cheng Shao at 2026-03-11T15:00:42-04:00
hadrian: remove the broken bench flavour
This patch removes the bench flavour from hadrian which has been
broken for years and not used for actual benchmarking (for which
`perf`/`release` is used instead). Closes #26825.
- - - - -
c3e64915 by Simon Jakobi at 2026-03-11T15:01:31-04:00
Add regression test for #18186
The original TypeInType language extension is replaced with
DataKinds+PolyKinds for compatibility.
Closes #18186.
- - - - -
664996c7 by Andreas Klebinger at 2026-03-11T15:02:16-04:00
Bump nofib submodule.
We accrued a number of nofib fixes we want to have here.
- - - - -
517cf64e by Simon Jakobi at 2026-03-11T15:03:03-04:00
Add regression test for #15907
Closes #15907.
- - - - -
fff362cf by Simon Jakobi at 2026-03-11T15:03:49-04:00
Ensure T14272 is run in optasm way
Closes #16539.
- - - - -
ec81ec2c by Simon Jakobi at 2026-03-11T15:03:49-04:00
Add regression test for #24632
Closes #24632.
- - - - -
cefec47b by Simon Jakobi at 2026-03-11T15:03:50-04:00
Fix module name of T9675: T6975 -> T9675
- - - - -
d3690ae8 by Andreas Klebinger at 2026-03-11T15:04:31-04:00
User guide: Clarify phase control on INLINEABLE[foo] pragmas.
Fixes #26851
- - - - -
e7054934 by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #12694
Closes #12694.
- - - - -
4756d9f6 by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #16275
Closes #16275.
- - - - -
34b7e2c1 by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #14908
Closes #14908.
- - - - -
4243db3d by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #14151
Closes #14151.
- - - - -
0e9f1453 by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #12640
Closes #12640.
- - - - -
ae606c7f by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #15588
Closes #15588.
- - - - -
5a38ce4e by Simon Jakobi at 2026-03-11T15:05:16-04:00
Add regression test for #9445
Closes #9445.
- - - - -
d054b467 by Cheng Shao at 2026-03-11T15:05:59-04:00
compiler: implement string interning logic for BCONPtrFS
This patch adds a `FastStringEnv`-based cache of `MallocStrings`
requests to `Interp`, so that when we load bytecode with many
breakpoints that share the same module names & unit ids, we reuse the
allocated remote pointers instead of issuing duplicte `MallocStrings`
requests and bloating the C heap. Closes #26995.
- - - - -
b85a0293 by Simon Jakobi at 2026-03-11T15:06:41-04:00
Add perf test for #1216
Closes #1216.
- - - - -
cd7f7420 by Sylvain Henry at 2026-03-11T15:07:58-04:00
JS: check that tuple constructors are linked (#23709)
Test js-mk_tup was failing before because tuple constructors weren't
linked in. It's no longer an issue after the linker fixes.
- - - - -
d57f01a4 by Matthew Pickering at 2026-03-11T15:08:40-04:00
testsuite: Add test for foreign import prim with unboxed tuple return
This commit just adds a test that foreign import prim works with unboxed
sums.
- - - - -
23d111ce by Matthew Pickering at 2026-03-11T15:08:41-04:00
Return a valid pointer in advanceStackFrameLocationzh
When there is no next stack chunk, `advanceStackFrameLocationzh` used to
return NULL in the pointer-typed StackSnapshot# result slot.
Even though the caller treats that case as "no next frame", the result is
still materialized in a GC-visible pointer slot. If a GC observes the raw
NULL there, stack decoding can crash.
Fix this by ensuring the dead pointer slot contains a valid closure
pointer. Also make the optional result explicit by returning an unboxed
sum instead of a tuple with a separate tag.
Fixes #27009
- - - - -
4c58a3ae by Cheng Shao at 2026-03-11T15:09:22-04:00
hadrian: build profiled dynamic objects with -dynamic-too
This patch enables hadrian to build profiled dynamic objects with
`-dynamic-too`, addressing a build parallelism bottleneck in release
pipelines. Closes #27010.
- - - - -
5a383cdd by Simon Peyton Jones at 2026-03-13T16:19:52+00:00
Fix evaluated-ness bug in Simplifier
This fixes #26548, an error which meant that we were failing to
attach evaluated-ness flags to case-alternative-bound variables
- - - - -
fbc77b0b by Simon Peyton Jones at 2026-03-13T16:19:52+00:00
Be a little less eager to inline
---> OtherCon [] = TrivArg
OtherCon _ = NonTrivArg
Make inlining a tiny bit more eager
---> OtherCon [] = NonTrivArg
In particular
x = mkSymMCo mco
where mco is evaluated. We want that to inline, especially if the
let is strict. Makes a significant difference in Rewrite.hs,
Test case T9872b
OtherCon [] arguments aren't interesting
---> OtherCon [] = TrivArg
Remove white space
Be a little less keen to inline
This commit changes interestingArg to treat lambda as NonTrivArg
rather than ValueArg. That makes parser combinators a bit less
keen to inline. E.g.
<|> p1 p2 = \x -> case p1 x of
Yes -> ...
No -> ...
If we have a call (<|> arg1 arg2) where arg1 is a parser, and hence
often visibly a lambda, it's no so great to inline <|>, because we
are still stuck on x.
This affects for example T17516
Just an experiment.
- - - - -
8968ee87 by Simon Peyton Jones at 2026-03-13T16:19:52+00:00
Wibbles
In particular, a lambda is a value argument in interestingArg
For some reason I had changed this and it made many things worse
This wibble puts it back!
- - - - -
430ab719 by Simon Peyton Jones at 2026-03-13T16:19:52+00:00
Tracing in SpecConstr only
- - - - -
e4e39934 by Simon Peyton Jones at 2026-03-13T16:19:52+00:00
Lambda arguments are values in interestingArg
This matters a lot!!!
- - - - -
6903d070 by Simon Peyton Jones at 2026-03-13T16:19:52+00:00
Make OtherCon unfoldings more eager to inline (again)
New code:
OtherCon [] -> NonTrivArg -- It's evaluated, but that's all we know
OtherCon _ -> ValueArg -- Evaluated and we know it isn't these constructors
-- See (IA2) in Note [Interesting arguments]
Reasons explained in (IA2), in `GHC.Internal.Bignum.Integer`.
Also (for OtherCon []): in the compiler itself
x = mkSymMCo mco
where mco is evaluated. We want mkSymMCo to inline, especially if the
let is strict. Makes a significant difference in Rewrite.hs,
Test case T9872b
- - - - -
c2c26b21 by Simon Peyton Jones at 2026-03-13T16:19:53+00:00
Once again try
OtherCon [] -> TrivArg -- It's evaluated, but that's all we know
Reason: much fruitless inlining of maMB in T18140, pushes up
compile times
- - - - -
544 changed files:
- .gitlab-ci.yml
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .gitlab/rel_eng/fetch-gitlab-artifacts/fetch_gitlab.py
- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Builtin/Names/TH.hs
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/Builtin/Types.hs
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/Cmm/MachOp.hs
- compiler/GHC/Cmm/Node.hs
- compiler/GHC/Cmm/Utils.hs
- compiler/GHC/CmmToAsm/AArch64/CodeGen.hs
- compiler/GHC/CmmToAsm/Config.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToAsm/X86/Instr.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/FloatIn.hs
- compiler/GHC/Core/Opt/FloatOut.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Config/CmmToAsm.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Errors/Ppr.hs
- compiler/GHC/HsToCore/Errors/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Ext/Utils.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Linker/Dynamic.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/String.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/HsType.hs
- + compiler/GHC/Rename/Lit.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Runtime/Interpreter/Init.hs
- compiler/GHC/Runtime/Interpreter/JS.hs
- compiler/GHC/Runtime/Interpreter/Types.hs
- compiler/GHC/Runtime/Interpreter/Wasm.hs
- compiler/GHC/StgToCmm/Expr.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/Object.hs
- compiler/GHC/StgToJS/Prim.hs
- compiler/GHC/SysTools/Cpp.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Foreign.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Instance/Typeable.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/SourceText.hs
- compiler/GHC/Types/Tickish.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Error.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Pat.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- + docs/users_guide/10.0.1-notes.rst
- docs/users_guide/9.16.1-notes.rst
- docs/users_guide/eventlog-formats.rst
- docs/users_guide/exts/explicit_namespaces.rst
- docs/users_guide/exts/pragmas.rst
- + docs/users_guide/exts/qualified_strings.rst
- docs/users_guide/exts/rewrite_rules.rst
- docs/users_guide/ghci.rst
- docs/users_guide/phases.rst
- docs/users_guide/using-optimisation.rst
- docs/users_guide/using.rst
- docs/users_guide/wasm.rst
- ghc/GHCi/UI.hs
- hadrian/README.md
- hadrian/bootstrap/generate_bootstrap_plans
- hadrian/bootstrap/plan-9_10_1.json
- hadrian/bootstrap/plan-9_10_2.json
- + hadrian/bootstrap/plan-9_10_3.json
- hadrian/bootstrap/plan-bootstrap-9_10_1.json
- hadrian/bootstrap/plan-bootstrap-9_10_2.json
- + hadrian/bootstrap/plan-bootstrap-9_10_3.json
- hadrian/build-cabal
- hadrian/doc/flavours.md
- hadrian/hadrian.cabal
- hadrian/src/CommandLine.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/Compile.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/GenPrimopCode.hs
- hadrian/src/Settings/Builders/Ghc.hs
- − hadrian/src/Settings/Flavours/Benchmark.hs
- libraries/base/changelog.md
- libraries/base/src/Control/Arrow.hs
- libraries/base/src/Data/Bool.hs
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NubOrdSet.hs
- libraries/base/src/GHC/Base.hs
- libraries/base/src/GHC/Exts.hs
- libraries/base/src/GHC/Fingerprint.hs
- libraries/base/src/GHC/ResponseFile.hs
- libraries/base/src/GHC/Unicode.hs
- libraries/base/src/System/Exit.hs
- libraries/base/src/System/IO.hs
- libraries/base/src/System/IO/OS.hs
- libraries/base/src/System/Info.hs
- libraries/base/tests/IO/T18832.hs
- libraries/ghc-boot-th/GHC/Boot/TH/Quote.hs
- libraries/ghc-experimental/CHANGELOG.md
- libraries/ghc-experimental/src/GHC/Stack/Annotation/Experimental.hs
- + libraries/ghc-experimental/tests/Makefile
- + libraries/ghc-experimental/tests/all.T
- + libraries/ghc-experimental/tests/backtraces/Makefile
- + libraries/ghc-experimental/tests/backtraces/T26806a.hs
- + libraries/ghc-experimental/tests/backtraces/T26806a.stderr
- + libraries/ghc-experimental/tests/backtraces/T26806b.hs
- + libraries/ghc-experimental/tests/backtraces/T26806b.stderr
- + libraries/ghc-experimental/tests/backtraces/T26806c.hs
- + libraries/ghc-experimental/tests/backtraces/T26806c.stderr
- + libraries/ghc-experimental/tests/backtraces/all.T
- libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
- libraries/ghc-internal/cbits/Stack.cmm
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Control/Arrow.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/Fix.hs
- libraries/ghc-internal/src/GHC/Internal/Control/Monad/ST/Lazy/Imp.hs
- − libraries/ghc-internal/src/GHC/Internal/Data/Bool.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Function.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Identity.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Bool.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Type/Ord.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Version.hs
- − libraries/ghc-internal/src/GHC/Internal/Data/Version.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/ManagedThreadPool.hs
- libraries/ghc-internal/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Fingerprint.hs
- libraries/ghc-internal/src/GHC/Internal/GHCi/Helpers.hs
- libraries/ghc-internal/src/GHC/Internal/IO/FD.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Text.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Types.hs
- libraries/ghc-internal/src/GHC/Internal/JS/Prim.hs
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- + libraries/ghc-internal/src/GHC/Internal/Prim.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags/Test.hsc
- − libraries/ghc-internal/src/GHC/Internal/ResponseFile.hs
- libraries/ghc-internal/src/GHC/Internal/STM.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- − libraries/ghc-internal/src/GHC/Internal/System/Exit.hs
- libraries/ghc-internal/src/GHC/Internal/System/IO.hs
- − libraries/ghc-internal/src/GHC/Internal/System/IO/OS.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lift.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Monad.hs
- − libraries/ghc-internal/src/GHC/Internal/TH/Quote.hs
- libraries/ghc-internal/src/GHC/Internal/TypeError.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Version.hs
- + libraries/ghc-internal/tests/backtraces/T15395.hs
- + libraries/ghc-internal/tests/backtraces/T15395.stdout
- libraries/ghc-internal/tests/backtraces/all.T
- libraries/ghc-internal/tests/stack-annotation/ann_frame001.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame002.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame003.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame004.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame005.stdout
- libraries/ghc-internal/tools/ucd2haskell/exe/UCD2Haskell/ModuleGenerators.hs
- libraries/template-haskell-quasiquoter
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- m4/fptools_happy.m4
- nofib
- rts/Linker.c
- rts/LinkerInternals.h
- rts/PrimOps.cmm
- rts/RtsSymbols.c
- rts/Threads.c
- rts/Threads.h
- rts/include/rts/Threads.h
- rts/include/stg/MiscClosures.h
- rts/linker/Elf.c
- rts/linker/MachO.c
- rts/linker/PEi386.c
- testsuite/driver/cpu_features.py
- testsuite/driver/perf_notes.py
- testsuite/tests/arrows/should_compile/T21301.stderr
- testsuite/tests/codeGen/should_compile/debug.stdout
- + testsuite/tests/codeGen/should_fail/T26958.hs
- testsuite/tests/codeGen/should_fail/all.T
- testsuite/tests/codeGen/should_gen_asm/all.T
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-minmax.hs
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-int64-mul.hs
- + testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.asm
- + testsuite/tests/codeGen/should_gen_asm/avx512-word64-minmax.hs
- + testsuite/tests/corelint/T15907.hs
- + testsuite/tests/corelint/T15907A.hs
- testsuite/tests/corelint/all.T
- testsuite/tests/deSugar/should_compile/T16615.stderr
- testsuite/tests/deSugar/should_compile/T2431.stderr
- testsuite/tests/deSugar/should_fail/DsStrictFail.stderr
- testsuite/tests/deSugar/should_run/T20024.stderr
- testsuite/tests/deSugar/should_run/dsrun005.stderr
- testsuite/tests/deSugar/should_run/dsrun007.stderr
- testsuite/tests/deSugar/should_run/dsrun008.stderr
- + testsuite/tests/dependent/should_fail/SelfDepCls.hs
- + testsuite/tests/dependent/should_fail/SelfDepCls.stderr
- + testsuite/tests/dependent/should_fail/T15588.hs
- + testsuite/tests/dependent/should_fail/T15588.stderr
- testsuite/tests/dependent/should_fail/all.T
- testsuite/tests/deriving/should_run/T9576.stderr
- testsuite/tests/diagnostic-codes/codes.stdout
- testsuite/tests/dmdanal/should_compile/T16029.stdout
- testsuite/tests/driver/T4437.hs
- testsuite/tests/ffi/should_compile/all.T
- + testsuite/tests/ffi/should_run/PrimFFIUnboxedSum.hs
- + testsuite/tests/ffi/should_run/PrimFFIUnboxedSum.stdout
- + testsuite/tests/ffi/should_run/PrimFFIUnboxedSum_cmm.cmm
- testsuite/tests/ffi/should_run/all.T
- testsuite/tests/ghc-api/annotations-literals/literals.stdout
- testsuite/tests/ghc-api/annotations-literals/parsed.hs
- + testsuite/tests/ghci-wasm/T26998.hs
- testsuite/tests/ghci-wasm/all.T
- testsuite/tests/ghci/scripts/Defer02.stderr
- testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout
- testsuite/tests/ghci/scripts/T10963.stderr
- testsuite/tests/ghci/scripts/T15325.stderr
- + testsuite/tests/ghci/scripts/T24632.hs
- + testsuite/tests/ghci/scripts/T24632.script
- + testsuite/tests/ghci/scripts/T24632.stdout
- testsuite/tests/ghci/scripts/T4175.stdout
- testsuite/tests/ghci/scripts/all.T
- testsuite/tests/ghci/should_run/all.T
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- 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/interface-stability/template-haskell-exports.stdout
- + testsuite/tests/javascript/T24886.hs
- + testsuite/tests/javascript/T24886.stderr
- + testsuite/tests/javascript/T24886.stdout
- testsuite/tests/javascript/all.T
- testsuite/tests/javascript/js-mk_tup.hs
- testsuite/tests/javascript/js-mk_tup.stdout
- − testsuite/tests/linear/should_compile/LinearListComprehension.hs
- testsuite/tests/linear/should_compile/all.T
- testsuite/tests/linear/should_fail/T25081.hs
- testsuite/tests/linear/should_fail/T25081.stderr
- testsuite/tests/linters/Makefile
- testsuite/tests/mdo/should_fail/mdofail006.stderr
- testsuite/tests/module/all.T
- + testsuite/tests/module/mod70b.hs
- + testsuite/tests/module/mod70b.stderr
- testsuite/tests/numeric/should_compile/T14170.stdout
- testsuite/tests/numeric/should_compile/T14465.stdout
- testsuite/tests/numeric/should_compile/T19641.stderr
- testsuite/tests/numeric/should_compile/T7116.stdout
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/overloadedrecflds/should_compile/all.T
- testsuite/tests/overloadedrecflds/should_run/all.T
- + testsuite/tests/parser/should_fail/NoBlockArgumentsFail4.hs
- + testsuite/tests/parser/should_fail/NoBlockArgumentsFail4.stderr
- testsuite/tests/parser/should_fail/NoBlockArgumentsFailArrowCmds.hs
- testsuite/tests/parser/should_fail/NoBlockArgumentsFailArrowCmds.stderr
- + testsuite/tests/parser/should_fail/NoDoAndIfThenElseArrowCmds.hs
- + testsuite/tests/parser/should_fail/NoDoAndIfThenElseArrowCmds.stderr
- + testsuite/tests/parser/should_fail/T26860ppr_overloaded.hs
- + testsuite/tests/parser/should_fail/T26860ppr_overloaded.stderr
- + testsuite/tests/parser/should_fail/T26860ppr_tylit.hs
- + testsuite/tests/parser/should_fail/T26860ppr_tylit.stderr
- testsuite/tests/parser/should_fail/all.T
- + testsuite/tests/parser/should_fail/badRuleMarker.hs
- + testsuite/tests/parser/should_fail/badRuleMarker.stderr
- + testsuite/tests/parser/should_fail/patFail010.hs
- + testsuite/tests/parser/should_fail/patFail010.stderr
- + testsuite/tests/parser/should_fail/patFail011.hs
- + testsuite/tests/parser/should_fail/patFail011.stderr
- + testsuite/tests/parser/should_fail/precOutOfRange.hs
- + testsuite/tests/parser/should_fail/precOutOfRange.stderr
- + testsuite/tests/parser/should_fail/unpack_data_con.hs
- + testsuite/tests/parser/should_fail/unpack_data_con.stderr
- testsuite/tests/patsyn/should_fail/T10426.stderr
- testsuite/tests/patsyn/should_fail/all.T
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail1.hs
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail1.stderr
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail2.hs
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail2.stderr
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail3.hs
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail3.stderr
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail4.hs
- + testsuite/tests/patsyn/should_fail/patsyn_where_fail4.stderr
- testsuite/tests/patsyn/should_run/ghci.stderr
- testsuite/tests/perf/compiler/T9675.hs
- + testsuite/tests/perf/should_run/T1216.hs
- + testsuite/tests/perf/should_run/T1216.stdout
- testsuite/tests/perf/should_run/all.T
- testsuite/tests/plugins/plugins10.stdout
- testsuite/tests/pmcheck/should_compile/T11303.hs
- + testsuite/tests/polykinds/T18186.hs
- + testsuite/tests/polykinds/T18186.stderr
- testsuite/tests/polykinds/all.T
- + testsuite/tests/qualified-strings/Makefile
- + testsuite/tests/qualified-strings/should_compile/Example/Length.hs
- + testsuite/tests/qualified-strings/should_compile/all.T
- + testsuite/tests/qualified-strings/should_compile/qstrings_redundant_pattern.hs
- + testsuite/tests/qualified-strings/should_compile/qstrings_redundant_pattern.stderr
- + testsuite/tests/qualified-strings/should_fail/Example/Length.hs
- + testsuite/tests/qualified-strings/should_fail/Makefile
- + testsuite/tests/qualified-strings/should_fail/all.T
- + testsuite/tests/qualified-strings/should_fail/qstrings_bad_expr.hs
- + testsuite/tests/qualified-strings/should_fail/qstrings_bad_expr.stderr
- + testsuite/tests/qualified-strings/should_fail/qstrings_bad_pat.hs
- + testsuite/tests/qualified-strings/should_fail/qstrings_bad_pat.stderr
- + testsuite/tests/qualified-strings/should_fail/qstrings_multiline_no_ext.hs
- + testsuite/tests/qualified-strings/should_fail/qstrings_multiline_no_ext.stderr
- + testsuite/tests/qualified-strings/should_run/Example/ByteStringAscii.hs
- + testsuite/tests/qualified-strings/should_run/Example/ByteStringUtf8.hs
- + testsuite/tests/qualified-strings/should_run/Example/Text.hs
- + testsuite/tests/qualified-strings/should_run/Makefile
- + testsuite/tests/qualified-strings/should_run/all.T
- + testsuite/tests/qualified-strings/should_run/qstrings_expr.hs
- + testsuite/tests/qualified-strings/should_run/qstrings_expr.stdout
- + testsuite/tests/qualified-strings/should_run/qstrings_pat.hs
- + testsuite/tests/qualified-strings/should_run/qstrings_pat.stdout
- + testsuite/tests/qualified-strings/should_run/qstrings_th.hs
- + testsuite/tests/qualified-strings/should_run/qstrings_th.stdout
- testsuite/tests/quasiquotation/qq005/test.T
- testsuite/tests/quasiquotation/qq006/test.T
- testsuite/tests/quotes/LiftErrMsgDefer.stderr
- testsuite/tests/quotes/QQError.stderr
- testsuite/tests/roles/should_compile/Roles1.stderr
- testsuite/tests/roles/should_compile/Roles13.stderr
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles2.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/roles/should_compile/T8958.stderr
- testsuite/tests/rts/linker/Makefile
- + testsuite/tests/rts/linker/T6107.hs
- + testsuite/tests/rts/linker/T6107.stdout
- + testsuite/tests/rts/linker/T6107_sym1.s
- + testsuite/tests/rts/linker/T6107_sym2.s
- testsuite/tests/rts/linker/all.T
- testsuite/tests/safeHaskell/safeLanguage/SafeLang15.stderr
- testsuite/tests/saks/should_compile/all.T
- testsuite/tests/showIface/all.T
- testsuite/tests/simd/should_run/all.T
- testsuite/tests/simd/should_run/doublex2_arith.hs
- testsuite/tests/simd/should_run/doublex2_arith.stdout
- testsuite/tests/simd/should_run/doublex2_arith_baseline.hs
- testsuite/tests/simd/should_run/doublex2_arith_baseline.stdout
- testsuite/tests/simd/should_run/floatx4_arith.hs
- testsuite/tests/simd/should_run/floatx4_arith.stdout
- testsuite/tests/simd/should_run/floatx4_arith_baseline.hs
- testsuite/tests/simd/should_run/floatx4_arith_baseline.stdout
- testsuite/tests/simd/should_run/int16x8_arith.hs
- testsuite/tests/simd/should_run/int16x8_arith.stdout
- testsuite/tests/simd/should_run/int16x8_arith_baseline.hs
- testsuite/tests/simd/should_run/int16x8_arith_baseline.stdout
- testsuite/tests/simd/should_run/int32x4_arith.hs
- testsuite/tests/simd/should_run/int32x4_arith.stdout
- testsuite/tests/simd/should_run/int32x4_arith_baseline.hs
- testsuite/tests/simd/should_run/int32x4_arith_baseline.stdout
- testsuite/tests/simd/should_run/int64x2_arith.hs
- testsuite/tests/simd/should_run/int64x2_arith.stdout
- testsuite/tests/simd/should_run/int64x2_arith_baseline.hs
- testsuite/tests/simd/should_run/int64x2_arith_baseline.stdout
- testsuite/tests/simd/should_run/int8x16_arith.hs
- testsuite/tests/simd/should_run/int8x16_arith.stdout
- testsuite/tests/simd/should_run/int8x16_arith_baseline.hs
- testsuite/tests/simd/should_run/int8x16_arith_baseline.stdout
- testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr
- + testsuite/tests/simplCore/should_compile/T12640.hs
- + testsuite/tests/simplCore/should_compile/T12640.stderr
- + testsuite/tests/simplCore/should_compile/T14908.hs
- + testsuite/tests/simplCore/should_compile/T14908_Deps.hs
- + testsuite/tests/simplCore/should_compile/T16122.hs
- + testsuite/tests/simplCore/should_compile/T16122.stderr
- + testsuite/tests/simplCore/should_compile/T26548.hs
- + testsuite/tests/simplCore/should_compile/T26548.stderr
- testsuite/tests/simplCore/should_compile/T26615.stderr
- + testsuite/tests/simplCore/should_compile/T26642.hs
- testsuite/tests/simplCore/should_compile/T3717.stderr
- testsuite/tests/simplCore/should_compile/T3772.stdout
- testsuite/tests/simplCore/should_compile/T4908.stderr
- testsuite/tests/simplCore/should_compile/T4930.stderr
- testsuite/tests/simplCore/should_compile/T7360.stderr
- testsuite/tests/simplCore/should_compile/T8274.stdout
- testsuite/tests/simplCore/should_compile/T9400.stderr
- + testsuite/tests/simplCore/should_compile/T9445.hs
- + testsuite/tests/simplCore/should_compile/TrickyJoins.hs
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_compile/noinline01.stderr
- testsuite/tests/simplCore/should_compile/par01.stderr
- testsuite/tests/th/QQTopError.stderr
- + testsuite/tests/th/T26862_th.script
- + testsuite/tests/th/T26862_th.stderr
- + testsuite/tests/th/T8306_th.script
- + testsuite/tests/th/T8306_th.stderr
- + testsuite/tests/th/T8306_th.stdout
- testsuite/tests/th/T8412.stderr
- + testsuite/tests/th/TH_EmptyLamCases.hs
- + testsuite/tests/th/TH_EmptyLamCases.stderr
- + testsuite/tests/th/TH_EmptyMultiIf.hs
- + testsuite/tests/th/TH_EmptyMultiIf.stderr
- testsuite/tests/th/TH_Roles2.stderr
- testsuite/tests/th/all.T
- testsuite/tests/type-data/should_run/T22332a.stderr
- testsuite/tests/typecheck/should_compile/T13032.stderr
- + testsuite/tests/typecheck/should_compile/T14151.hs
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- testsuite/tests/typecheck/should_compile/all.T
- + testsuite/tests/typecheck/should_fail/T12694.hs
- + testsuite/tests/typecheck/should_fail/T12694.stderr
- + testsuite/tests/typecheck/should_fail/T16275.stderr
- + testsuite/tests/typecheck/should_fail/T16275A.hs
- + testsuite/tests/typecheck/should_fail/T16275B.hs
- + testsuite/tests/typecheck/should_fail/T16275B.hs-boot
- + testsuite/tests/typecheck/should_fail/T26861.hs
- + testsuite/tests/typecheck/should_fail/T26861.stderr
- + testsuite/tests/typecheck/should_fail/T26862.hs
- + testsuite/tests/typecheck/should_fail/T26862.stderr
- testsuite/tests/typecheck/should_fail/T8306.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_run/T10284.stderr
- testsuite/tests/typecheck/should_run/T13838.stderr
- testsuite/tests/typecheck/should_run/T9497a-run.stderr
- testsuite/tests/typecheck/should_run/T9497b-run.stderr
- testsuite/tests/typecheck/should_run/T9497c-run.stderr
- testsuite/tests/unboxedsums/all.T
- + testsuite/tests/unboxedsums/unboxedsums4p.hs
- + testsuite/tests/unboxedsums/unboxedsums4p.stderr
- testsuite/tests/unsatisfiable/T23816.stderr
- testsuite/tests/unsatisfiable/UnsatDefer.stderr
- testsuite/tests/vdq-rta/should_compile/all.T
- + testsuite/tests/warnings/should_compile/SpecMultipleTysMono.hs
- + testsuite/tests/warnings/should_compile/SpecMultipleTysMono.stderr
- testsuite/tests/warnings/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/genprimopcode/Main.hs
- utils/haddock/doc/.gitignore
- utils/haddock/doc/Makefile
- + utils/haddock/doc/_static/haddock-custom.css
- utils/haddock/doc/conf.py
- utils/haddock/doc/markup.rst
- + utils/haddock/doc/snippets/.gitignore
- + utils/haddock/doc/snippets/Lists.hs
- + utils/haddock/doc/snippets/Makefile
- + utils/haddock/doc/snippets/Snippet-List-Bulleted.html
- + utils/haddock/doc/snippets/Snippet-List-Bulleted.tex
- + utils/haddock/doc/snippets/Snippet-List-Definition.html
- + utils/haddock/doc/snippets/Snippet-List-Definition.tex
- + utils/haddock/doc/snippets/Snippet-List-Enumerated.html
- + utils/haddock/doc/snippets/Snippet-List-Enumerated.tex
- + utils/haddock/doc/snippets/Snippet-List-Indentation.html
- + utils/haddock/doc/snippets/Snippet-List-Indentation.tex
- + utils/haddock/doc/snippets/Snippet-List-Multiline-Item.html
- + utils/haddock/doc/snippets/Snippet-List-Multiline-Item.tex
- + utils/haddock/doc/snippets/Snippet-List-Nested-Item.html
- + utils/haddock/doc/snippets/Snippet-List-Nested-Item.tex
- + utils/haddock/doc/snippets/Snippet-List-Not-Newline.html
- + utils/haddock/doc/snippets/Snippet-List-Not-Newline.tex
- + utils/haddock/doc/snippets/Snippet-List-Not-Separated.html
- + utils/haddock/doc/snippets/Snippet-List-Not-Separated.tex
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
- utils/haddock/html-test/ref/A.html
- utils/haddock/html-test/ref/Bug1004.html
- utils/haddock/html-test/ref/Bug1033.html
- utils/haddock/html-test/ref/Bug1103.html
- utils/haddock/html-test/ref/Bug548.html
- utils/haddock/html-test/ref/Bug923.html
- utils/haddock/html-test/ref/ConstructorPatternExport.html
- utils/haddock/html-test/ref/FunArgs.html
- utils/haddock/html-test/ref/Hash.html
- utils/haddock/html-test/ref/Instances.html
- utils/haddock/html-test/ref/LinearTypes.html
- utils/haddock/html-test/ref/RedactTypeSynonyms.html
- utils/haddock/html-test/ref/T23616.html
- utils/haddock/html-test/ref/Test.html
- utils/haddock/html-test/ref/TypeFamilies3.html
- utils/jsffi/dyld.mjs
- utils/jsffi/post-link.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/8c27a3ec59779dee26767e392490e8…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/8c27a3ec59779dee26767e392490e8…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/torsten.schmits/mwb-26-01/mp-backports] 3 commits: Don't store boot locations in finder cache
by Torsten Schmits (@torsten.schmits) 13 Mar '26
by Torsten Schmits (@torsten.schmits) 13 Mar '26
13 Mar '26
Torsten Schmits pushed to branch wip/torsten.schmits/mwb-26-01/mp-backports at Glasgow Haskell Compiler / GHC
Commits:
ff5e16b0 by Sjoerd Visscher at 2026-03-13T16:20:54+01:00
Don't store boot locations in finder cache
Partially reverts commit fff55592a7b
Amends add(Home)ModuleToFinder so that locations for boot files are not stored in the finder cache.
Removes InstalledModule field from InstalledFound constructor since it's the same as the key that was searched for.
- - - - -
ffceb7e6 by Sjoerd Visscher at 2026-03-13T16:36:00+01:00
Concentrate boot extension logic in Finder
With new mkHomeModLocation that takes an extra HscSource to add boot extensions if required.
- - - - -
65d1ec83 by Torsten Schmits at 2026-03-13T16:39:40+01:00
Add a complete pragma for `ModLocation`
- - - - -
10 changed files:
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Phases.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Location.hs
Changes:
=====================================
compiler/GHC/Driver/Backpack.hs
=====================================
@@ -788,7 +788,7 @@ summariseRequirement pn mod_name = do
let loc = srcLocSpan (mkSrcLoc (mkFastString (bkp_filename env)) 1 1)
let fc = hsc_FC hsc_env
- mod <- liftIO $ addHomeModuleToFinder fc home_unit mod_name location
+ mod <- liftIO $ addHomeModuleToFinder fc home_unit mod_name location HsigFile
extra_sig_imports <- liftIO $ findExtraSigImports hsc_env HsigFile mod_name
@@ -862,17 +862,14 @@ hsModuleToModSummary home_keys pn hsc_src modname
-- To add insult to injury, we don't even actually use
-- these filenames to figure out where the hi files go.
-- A travesty!
- let location0 = mkHomeModLocation2 fopts modname
+ let location = mkHomeModLocation fopts modname
(unsafeEncodeUtf $ unpackFS unit_fs </>
moduleNameSlashes modname)
- (case hsc_src of
+ (case hsc_src of
HsigFile -> os "hsig"
HsBootFile -> os "hs-boot"
HsSrcFile -> os "hs")
- -- DANGEROUS: bootifying can POISON the module finder cache
- let location = case hsc_src of
- HsBootFile -> addBootSuffixLocnOut location0
- _ -> location0
+ hsc_src
-- This duplicates a pile of logic in GHC.Driver.Make
hi_timestamp <- liftIO $ modificationTimeIfExists (ml_hi_file location)
hie_timestamp <- liftIO $ modificationTimeIfExists (ml_hie_file location)
@@ -903,7 +900,7 @@ hsModuleToModSummary home_keys pn hsc_src modname
this_mod <- liftIO $ do
let home_unit = hsc_home_unit hsc_env
let fc = hsc_FC hsc_env
- addHomeModuleToFinder fc home_unit modname location
+ addHomeModuleToFinder fc home_unit modname location hsc_src
let ms = ModSummary {
ms_mod = this_mod,
ms_hsc_src = hsc_src,
=====================================
compiler/GHC/Driver/Make.hs
=====================================
@@ -2122,16 +2122,23 @@ summariseFile hsc_env' home_unit old_summaries src_fn mb_phase maybe_buf
<- getPreprocessedImports hsc_env src_fn mb_phase maybe_buf
let fopts = initFinderOpts (hsc_dflags hsc_env)
+ (basename, extension) = splitExtension src_fn
- -- Make a ModLocation for this file
- let location = mkHomeModLocation fopts pi_mod_name (unsafeEncodeUtf src_fn)
+ hsc_src
+ | isHaskellSigSuffix (drop 1 extension) = HsigFile
+ | isHaskellBootSuffix (drop 1 extension) = HsBootFile
+ | otherwise = HsSrcFile
+
+ -- Make a ModLocation for this file, adding the @-boot@ suffix to
+ -- all paths if the original was a boot file.
+ location = mkHomeModLocation fopts pi_mod_name (unsafeEncodeUtf basename) (unsafeEncodeUtf extension) hsc_src
-- Tell the Finder cache where it is, so that subsequent calls
-- to findModule will find it, even if it's not on any search path
mod <- liftIO $ do
let home_unit = hsc_home_unit hsc_env
let fc = hsc_FC hsc_env
- addHomeModuleToFinder fc home_unit pi_mod_name location
+ addHomeModuleToFinder fc home_unit pi_mod_name location hsc_src
liftIO $ makeNewModSummary hsc_env $ MakeNewModSummary
{ nms_src_fn = src_fn
@@ -2166,13 +2173,10 @@ checkSummaryHash
-- and it was likely flushed in depanal. This is not technically
-- needed when we're called from sumariseModule but it shouldn't
-- hurt.
- -- Also, only add to finder cache for non-boot modules as the finder cache
- -- makes sure to add a boot suffix for boot files.
- _ <- do
- let fc = hsc_FC hsc_env
- case ms_hsc_src old_summary of
- HsSrcFile -> addModuleToFinder fc (ms_mod old_summary) location
- _ -> return ()
+ let fc = hsc_FC hsc_env
+ mod = ms_mod old_summary
+ hsc_src = ms_hsc_src old_summary
+ addModuleToFinder fc mod location hsc_src
hi_timestamp <- modificationTimeIfExists (ml_hi_file location)
hie_timestamp <- modificationTimeIfExists (ml_hie_file location)
@@ -2224,7 +2228,7 @@ summariseModule hsc_env' home_unit old_summary_map is_boot (L _ wanted_mod) mb_p
find_it :: IO SummariseResult
find_it = do
- found <- findImportedModule hsc_env wanted_mod mb_pkg
+ found <- findImportedModuleWithIsBoot hsc_env wanted_mod is_boot mb_pkg
case found of
Found location mod
| isJust (ml_hs_file location) ->
@@ -2242,10 +2246,7 @@ summariseModule hsc_env' home_unit old_summary_map is_boot (L _ wanted_mod) mb_p
just_found location mod = do
-- Adjust location to point to the hs-boot source file,
-- hi file, object file, when is_boot says so
- let location' = case is_boot of
- IsBoot -> addBootSuffixLocn location
- NotBoot -> location
- src_fn = expectJust "summarise2" (ml_hs_file location')
+ let src_fn = expectJust "summarise2" (ml_hs_file location)
-- Check that it exists
-- It might have been deleted since the Finder last found it
@@ -2255,7 +2256,7 @@ summariseModule hsc_env' home_unit old_summary_map is_boot (L _ wanted_mod) mb_p
-- .hs-boot file doesn't exist.
Nothing -> return NotThere
Just h -> do
- fresult <- new_summary_cache_check location' mod src_fn h
+ fresult <- new_summary_cache_check location mod src_fn h
return $ case fresult of
Left err -> FoundHomeWithError (moduleUnitId mod, err)
Right ms -> FoundHome ms
=====================================
compiler/GHC/Driver/MakeFile.hs
=====================================
@@ -307,7 +307,7 @@ findDependency :: HscEnv
findDependency hsc_env srcloc pkg imp dep_boot = do
-- Find the module; this will be fast because
-- we've done it once during downsweep
- findImportedModule hsc_env imp pkg >>= \case
+ findImportedModuleWithIsBoot hsc_env imp dep_boot pkg >>= \case
Found loc dep_mod ->
pure DepHi {
dep_mod,
@@ -356,10 +356,9 @@ writeDependencies include_pkgs root hdl suffixes node deps =
-- e.g. A.o : B.hi
-- A.x_o : B.x_hi
import_dep = \case
- DepHi {dep_path, dep_boot, dep_unit}
+ DepHi {dep_path, dep_unit}
| isNothing dep_unit || include_pkgs
- , let path = addBootSuffix_maybe dep_boot dep_path
- -> [([obj], hi) | (obj, hi) <- zip obj_files (suffixed path)]
+ -> [([obj], hi) | (obj, hi) <- zip obj_files (suffixed dep_path)]
| otherwise
-> []
=====================================
compiler/GHC/Driver/Phases.hs
=====================================
@@ -23,6 +23,7 @@ module GHC.Driver.Phases (
isDynLibSuffix,
isHaskellUserSrcSuffix,
isHaskellSigSuffix,
+ isHaskellBootSuffix,
isSourceSuffix,
isHaskellishTarget,
@@ -234,7 +235,7 @@ phaseInputExt Js = "js"
phaseInputExt StopLn = "o"
haskellish_src_suffixes, backpackish_suffixes, haskellish_suffixes, cish_suffixes,
- js_suffixes, haskellish_user_src_suffixes, haskellish_sig_suffixes
+ js_suffixes, haskellish_user_src_suffixes, haskellish_sig_suffixes, haskellish_boot_suffixes
:: [String]
-- When a file with an extension in the haskellish_src_suffixes group is
-- loaded in --make mode, its imports will be loaded too.
@@ -247,7 +248,8 @@ js_suffixes = [ "js" ]
-- Will not be deleted as temp files:
haskellish_user_src_suffixes =
- haskellish_sig_suffixes ++ [ "hs", "lhs", "hs-boot", "lhs-boot" ]
+ haskellish_sig_suffixes ++ haskellish_boot_suffixes ++ [ "hs", "lhs" ]
+haskellish_boot_suffixes = [ "hs-boot", "lhs-boot" ]
haskellish_sig_suffixes = [ "hsig", "lhsig" ]
backpackish_suffixes = [ "bkp" ]
@@ -265,11 +267,12 @@ dynlib_suffixes platform = case platformOS platform of
_ -> ["so"]
isHaskellishSuffix, isBackpackishSuffix, isHaskellSrcSuffix, isCishSuffix,
- isHaskellUserSrcSuffix, isJsSuffix, isHaskellSigSuffix
+ isHaskellUserSrcSuffix, isJsSuffix, isHaskellSigSuffix, isHaskellBootSuffix
:: String -> Bool
isHaskellishSuffix s = s `elem` haskellish_suffixes
isBackpackishSuffix s = s `elem` backpackish_suffixes
isHaskellSigSuffix s = s `elem` haskellish_sig_suffixes
+isHaskellBootSuffix s = s `elem` haskellish_boot_suffixes
isHaskellSrcSuffix s = s `elem` haskellish_src_suffixes
isCishSuffix s = s `elem` cish_suffixes
isJsSuffix s = s `elem` js_suffixes
=====================================
compiler/GHC/Driver/Pipeline/Execute.hs
=====================================
@@ -725,7 +725,7 @@ runHscPhase pipe_env hsc_env0 input_fn src_flavour = do
mod <- do
let home_unit = hsc_home_unit hsc_env
let fc = hsc_FC hsc_env
- addHomeModuleToFinder fc home_unit mod_name location
+ addHomeModuleToFinder fc home_unit mod_name location src_flavour
-- Make the ModSummary to hand to hscMain
let
@@ -769,24 +769,18 @@ mkOneShotModLocation :: PipeEnv -> DynFlags -> HscSource -> ModuleName -> IO Mod
mkOneShotModLocation pipe_env dflags src_flavour mod_name = do
let PipeEnv{ src_basename=basename,
src_suffix=suff } = pipe_env
- let location1 = mkHomeModLocation2 fopts mod_name (unsafeEncodeUtf basename) (unsafeEncodeUtf suff)
-
- -- Boot-ify it if necessary
- let location2
- | HsBootFile <- src_flavour = addBootSuffixLocnOut location1
- | otherwise = location1
-
+ let location1 = mkHomeModLocation fopts mod_name (unsafeEncodeUtf basename) (unsafeEncodeUtf suff) src_flavour
-- Take -ohi into account if present
-- This can't be done in mkHomeModuleLocation because
-- it only applies to the module being compiles
let ohi = outputHi dflags
- location3 | Just fn <- ohi = location2{ ml_hi_file_ospath = unsafeEncodeUtf fn }
- | otherwise = location2
+ location2 | Just fn <- ohi = location1{ ml_hi_file_ospath = unsafeEncodeUtf fn }
+ | otherwise = location1
let dynohi = dynOutputHi dflags
- location4 | Just fn <- dynohi = location3{ ml_dyn_hi_file_ospath = unsafeEncodeUtf fn }
- | otherwise = location3
+ location3 | Just fn <- dynohi = location2{ ml_dyn_hi_file_ospath = unsafeEncodeUtf fn }
+ | otherwise = location2
-- Take -o into account if present
-- Very like -ohi, but we must *only* do this if we aren't linking
@@ -799,11 +793,11 @@ mkOneShotModLocation pipe_env dflags src_flavour mod_name = do
location5 | Just ofile <- expl_o_file
, let dyn_ofile = fromMaybe (ofile -<.> dynObjectSuf_ dflags) expl_dyn_o_file
, isNoLink (ghcLink dflags)
- = location4 { ml_obj_file_ospath = unsafeEncodeUtf ofile
+ = location3 { ml_obj_file_ospath = unsafeEncodeUtf ofile
, ml_dyn_obj_file_ospath = unsafeEncodeUtf dyn_ofile }
| Just dyn_ofile <- expl_dyn_o_file
- = location4 { ml_dyn_obj_file_ospath = unsafeEncodeUtf dyn_ofile }
- | otherwise = location4
+ = location3 { ml_dyn_obj_file_ospath = unsafeEncodeUtf dyn_ofile }
+ | otherwise = location3
return location5
where
fopts = initFinderOpts dflags
=====================================
compiler/GHC/Iface/Load.hs
=====================================
@@ -928,9 +928,9 @@ findAndReadIface hsc_env doc_str mod wanted_mod hi_boot_file = do
else do
let fopts = initFinderOpts dflags
-- Look for the file
- mb_found <- liftIO (findExactModule fc fopts other_fopts unit_state mhome_unit mod)
+ mb_found <- liftIO (findExactModule fc fopts other_fopts unit_state mhome_unit mod hi_boot_file)
case mb_found of
- InstalledFound (addBootSuffixLocn_maybe hi_boot_file -> loc) mod -> do
+ InstalledFound loc -> do
-- See Note [Home module load error]
case mhome_unit of
Just home_unit
=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -663,7 +663,7 @@ initLinkDepsOpts hsc_env = opts
Maybe.Failed err -> pure (Maybe.Failed err)
Maybe.Succeeded iface ->
find_location mod <&> \case
- InstalledFound loc _ -> Maybe.Succeeded (iface, loc)
+ InstalledFound loc -> Maybe.Succeeded (iface, loc)
err -> Maybe.Failed $
cannotFindInterface unit_state home_unit
(targetProfile dflags) (moduleName mod) err
@@ -671,7 +671,7 @@ initLinkDepsOpts hsc_env = opts
find_location mod =
liftIO $
findExactModule (hsc_FC hsc_env) (initFinderOpts dflags)
- other_fopts unit_state home_unit (toUnitId <$> mod)
+ other_fopts unit_state home_unit (toUnitId <$> mod) NotBoot
other_fopts = initFinderOpts . homeUnitEnv_dflags <$> hsc_HUG hsc_env
=====================================
compiler/GHC/Unit/Finder.hs
=====================================
@@ -15,6 +15,7 @@ module GHC.Unit.Finder (
initFinderCache,
flushFinderCaches,
findImportedModule,
+ findImportedModuleWithIsBoot,
findPluginModule,
findExactModule,
findHomeModule,
@@ -62,6 +63,7 @@ import GHC.Utils.Panic
import GHC.Linker.Types
import GHC.Types.PkgQual
+import GHC.Types.SourceFile
import GHC.Fingerprint
import Data.IORef
@@ -171,6 +173,13 @@ findImportedModule hsc_env mod pkg_qual =
query <- hscUnitIndexQuery hsc_env
findImportedModuleNoHsc fc fopts (hsc_unit_env hsc_env) query home_module_map mhome_unit mod pkg_qual
+findImportedModuleWithIsBoot :: HscEnv -> ModuleName -> IsBootInterface -> PkgQual -> IO FindResult
+findImportedModuleWithIsBoot hsc_env mod is_boot pkg_qual = do
+ res <- findImportedModule hsc_env mod pkg_qual
+ case (res, is_boot) of
+ (Found loc mod, IsBoot) -> return (Found (addBootSuffixLocn loc) mod)
+ _ -> return res
+
findImportedModuleNoHsc
:: FinderCache
-> FinderOpts
@@ -261,15 +270,19 @@ findPluginModule fc fopts units query Nothing mod_name =
-- reading the interface for a module mentioned by another interface,
-- for example (a "system import").
-findExactModule :: FinderCache -> FinderOpts -> UnitEnvGraph FinderOpts -> UnitState -> Maybe HomeUnit -> InstalledModule -> IO InstalledFindResult
-findExactModule fc fopts other_fopts unit_state mhome_unit mod = do
- case mhome_unit of
+findExactModule :: FinderCache -> FinderOpts -> UnitEnvGraph FinderOpts -> UnitState -> Maybe HomeUnit -> InstalledModule -> IsBootInterface -> IO InstalledFindResult
+findExactModule fc fopts other_fopts unit_state mhome_unit mod is_boot = do
+ res <- case mhome_unit of
Just home_unit
| isHomeInstalledModule home_unit mod
-> findInstalledHomeModule fc fopts (homeUnitId home_unit) (moduleName mod)
| Just home_fopts <- HUG.unitEnv_lookup_maybe (moduleUnit mod) other_fopts
-> findInstalledHomeModule fc home_fopts (moduleUnit mod) (moduleName mod)
_ -> findPackageModule fc unit_state fopts mod
+ case (res, is_boot) of
+ (InstalledFound loc, IsBoot) -> return (InstalledFound (addBootSuffixLocn loc))
+ _ -> return res
+
-- -----------------------------------------------------------------------------
-- Helpers
@@ -329,7 +342,7 @@ findLookupResult fc fopts r = case r of
-- with just the location of the thing that was
-- instantiated; you probably also need all of the
-- implicit locations from the instances
- InstalledFound loc _ -> return (Found loc m)
+ InstalledFound loc -> return (Found loc m)
InstalledNoPackage _ -> return (NoPackage (moduleUnit m))
InstalledNotFound fp _ -> return (NotFound{ fr_paths = fmap unsafeDecodeUtf fp, fr_pkg = Just (moduleUnit m)
, fr_pkgs_hidden = []
@@ -374,16 +387,18 @@ modLocationCache fc mod do_this = do
addToFinderCache fc mod result
return result
-addModuleToFinder :: FinderCache -> Module -> ModLocation -> IO ()
-addModuleToFinder fc mod loc = do
+addModuleToFinder :: FinderCache -> Module -> ModLocation -> HscSource -> IO ()
+addModuleToFinder fc mod loc src_flavour = do
let imod = toUnitId <$> mod
- addToFinderCache fc imod (InstalledFound loc imod)
+ unless (src_flavour == HsBootFile) $
+ addToFinderCache fc imod (InstalledFound loc)
-- This returns a module because it's more convenient for users
-addHomeModuleToFinder :: FinderCache -> HomeUnit -> ModuleName -> ModLocation -> IO Module
-addHomeModuleToFinder fc home_unit mod_name loc = do
+addHomeModuleToFinder :: FinderCache -> HomeUnit -> ModuleName -> ModLocation -> HscSource -> IO Module
+addHomeModuleToFinder fc home_unit mod_name loc src_flavour = do
let mod = mkHomeInstalledModule home_unit mod_name
- addToFinderCache fc mod (InstalledFound loc mod)
+ unless (src_flavour == HsBootFile) $
+ addToFinderCache fc mod (InstalledFound loc)
return (mkHomeModule home_unit mod_name)
uncacheModule :: FinderCache -> HomeUnit -> ModuleName -> IO ()
@@ -399,7 +414,7 @@ findHomeModule fc fopts home_unit mod_name = do
let uid = homeUnitAsUnit home_unit
r <- findInstalledHomeModule fc fopts (homeUnitId home_unit) mod_name
return $ case r of
- InstalledFound loc _ -> Found loc (mkHomeModule home_unit mod_name)
+ InstalledFound loc -> Found loc (mkHomeModule home_unit mod_name)
InstalledNoPackage _ -> NoPackage uid -- impossible
InstalledNotFound fps _ -> NotFound {
fr_paths = fmap unsafeDecodeUtf fps,
@@ -424,7 +439,7 @@ findHomePackageModule fc fopts home_unit mod_name = do
let uid = RealUnit (Definite home_unit)
r <- findInstalledHomeModule fc fopts home_unit mod_name
return $ case r of
- InstalledFound loc _ -> Found loc (mkModule uid mod_name)
+ InstalledFound loc -> Found loc (mkModule uid mod_name)
InstalledNoPackage _ -> NoPackage uid -- impossible
InstalledNotFound fps _ -> NotFound {
fr_paths = fmap unsafeDecodeUtf fps,
@@ -494,7 +509,7 @@ findInstalledHomeModule fc fopts home_unit mod_name = do
-- This is important only when compiling the base package (where GHC.Prim
-- is a home module).
if mod `installedModuleEq` gHC_PRIM
- then return (InstalledFound (error "GHC.Prim ModLocation") mod)
+ then return (InstalledFound (error "GHC.Prim ModLocation"))
else searchPathExts search_dirs mod exts
-- | Prepend the working directory to the search path.
@@ -527,7 +542,7 @@ findPackageModule_ fc fopts mod pkg_conf = do
-- special case for GHC.Prim; we won't find it in the filesystem.
if mod `installedModuleEq` gHC_PRIM
- then return (InstalledFound (error "GHC.Prim ModLocation") mod)
+ then return (InstalledFound (error "GHC.Prim ModLocation"))
else
let
@@ -551,7 +566,7 @@ findPackageModule_ fc fopts mod pkg_conf = do
-- don't bother looking for it.
let basename = unsafeEncodeUtf $ moduleNameSlashes (moduleName mod)
loc = mk_hi_loc one basename
- in return $ InstalledFound loc mod
+ in return $ InstalledFound loc
_otherwise ->
searchPathExts import_dirs mod [(package_hisuf, mk_hi_loc)]
@@ -585,7 +600,7 @@ searchPathExts paths mod exts = search to_search
search ((file, loc) : rest) = do
b <- doesFileExist file
if b
- then return $ InstalledFound loc mod
+ then return $ InstalledFound loc
else search rest
mkHomeModLocationSearched :: FinderOpts -> ModuleName -> FileExt
@@ -627,10 +642,12 @@ mkHomeModLocationSearched fopts mod suff path basename =
-- ext
-- The filename extension of the source file (usually "hs" or "lhs").
-mkHomeModLocation :: FinderOpts -> ModuleName -> OsPath -> ModLocation
-mkHomeModLocation dflags mod src_filename =
- let (basename,extension) = OsPath.splitExtension src_filename
- in mkHomeModLocation2 dflags mod basename extension
+mkHomeModLocation :: FinderOpts -> ModuleName -> OsPath -> FileExt -> HscSource -> ModLocation
+mkHomeModLocation dflags mod src_basename ext hsc_src =
+ let loc = mkHomeModLocation2 dflags mod src_basename ext
+ in case hsc_src of
+ HsBootFile -> addBootSuffixLocnOut loc
+ _ -> loc
mkHomeModLocation2 :: FinderOpts
-> ModuleName
=====================================
compiler/GHC/Unit/Finder/Types.hs
=====================================
@@ -30,7 +30,7 @@ data FinderCache = FinderCache { fcModuleCache :: (IORef FinderCacheState)
}
data InstalledFindResult
- = InstalledFound ModLocation InstalledModule
+ = InstalledFound ModLocation
| InstalledNoPackage UnitId
| InstalledNotFound [OsPath] (Maybe UnitId)
=====================================
compiler/GHC/Unit/Module/Location.hs
=====================================
@@ -13,8 +13,6 @@ module GHC.Unit.Module.Location
)
, pattern ModLocation
, addBootSuffix
- , addBootSuffix_maybe
- , addBootSuffixLocn_maybe
, addBootSuffixLocn
, addBootSuffixLocnOut
, removeBootSuffix
@@ -24,7 +22,6 @@ where
import GHC.Prelude
import GHC.Data.OsPath
-import GHC.Unit.Types
import GHC.Utils.Outputable
import qualified System.OsString as OsString
@@ -96,26 +93,10 @@ removeBootSuffix pathWithBootSuffix =
Just path -> path
Nothing -> error "removeBootSuffix: no -boot suffix"
--- | Add the @-boot@ suffix if the @Bool@ argument is @True@
-addBootSuffix_maybe :: IsBootInterface -> OsPath -> OsPath
-addBootSuffix_maybe is_boot path = case is_boot of
- IsBoot -> addBootSuffix path
- NotBoot -> path
-
-addBootSuffixLocn_maybe :: IsBootInterface -> ModLocation -> ModLocation
-addBootSuffixLocn_maybe is_boot locn = case is_boot of
- IsBoot -> addBootSuffixLocn locn
- _ -> locn
-
-- | Add the @-boot@ suffix to all file paths associated with the module
addBootSuffixLocn :: ModLocation -> ModLocation
addBootSuffixLocn locn
- = locn { ml_hs_file_ospath = fmap addBootSuffix (ml_hs_file_ospath locn)
- , ml_hi_file_ospath = addBootSuffix (ml_hi_file_ospath locn)
- , ml_dyn_hi_file_ospath = addBootSuffix (ml_dyn_hi_file_ospath locn)
- , ml_obj_file_ospath = addBootSuffix (ml_obj_file_ospath locn)
- , ml_dyn_obj_file_ospath = addBootSuffix (ml_dyn_obj_file_ospath locn)
- , ml_hie_file_ospath = addBootSuffix (ml_hie_file_ospath locn) }
+ = addBootSuffixLocnOut locn { ml_hs_file_ospath = fmap addBootSuffix (ml_hs_file_ospath locn) }
-- | Add the @-boot@ suffix to all output file paths associated with the
-- module, not including the input file itself
@@ -157,3 +138,5 @@ pattern ModLocation
, ml_dyn_obj_file_ospath = unsafeEncodeUtf ml_dyn_obj_file
, ml_hie_file_ospath = unsafeEncodeUtf ml_hie_file
}
+
+{-# complete ModLocation #-}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b989904c813530b7f7c11da9de0ba6…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b989904c813530b7f7c11da9de0ba6…
You're receiving this email because of your account on gitlab.haskell.org.
1
0