Matthew Pickering pushed to branch wip/sort-usages at Glasgow Haskell Compiler / GHC Commits: 8201d1ba by Ian-Woo Kim at 2026-02-04T17:13:54+00:00 determinism: Sort Usages by fingerprint to ensure consistent ordering In some situations it has been observed that the ordering of usages can be non-determinstic in parallel builds. Therefore to be on the safe side we perform a sort on the usages field before writing them to the interface. Fixes #26877 - - - - - 3 changed files: - compiler/GHC/HsToCore/Usage.hs - compiler/GHC/Unit/Module/Deps.hs - testsuite/tests/driver/recomp016/recomp016.stdout Changes: ===================================== compiler/GHC/HsToCore/Usage.hs ===================================== @@ -36,7 +36,7 @@ import GHC.Data.Maybe import GHC.Data.FastString import Data.IORef -import Data.List (sortBy) +import Data.List (sortBy, sortOn) import Data.Map (Map) import qualified Data.Map as Map import qualified Data.Set as Set @@ -73,6 +73,8 @@ data UsageConfig = UsageConfig { uc_safe_implicit_imps_req :: !Bool -- ^ Are all implicit imports required to be safe for this Safe Haskell mode? } +-- | Build the list of 'Usage's that drives recompilation checking. +-- The resulting list is deterministically sorted (see 'usageFingerprint'). mkUsageInfo :: UsageConfig -> Plugins -> FinderCache -> UnitEnv -> Module -> ImportedMods -> [ImportUserSpec] -> NameSet -> [FilePath] -> [FilePath] -> [(Module, Fingerprint)] -> [Linkable] -> PkgsLoaded @@ -105,7 +107,10 @@ mkUsageInfo uc plugins fc unit_env } | (mod, hash) <- merged ] ++ object_usages - usages `seqList` return usages + + -- Sort all the Usages to ensure a deterministic ordering. + let sorted_usages = sortOn usageFingerprint usages + sorted_usages `seqList` return sorted_usages -- seq the list of Usages returned: occasionally these -- don't get evaluated for a while and we can end up hanging on to -- the entire collection of Ifaces. ===================================== compiler/GHC/Unit/Module/Deps.hs ===================================== @@ -17,6 +17,7 @@ module GHC.Unit.Module.Deps , noDependencies , pprDeps , Usage (..) + , usageFingerprint , HomeModImport (..) , HomeModImportedAvails (..) , ImportAvails (..) @@ -492,6 +493,17 @@ instance Binary Usage where i -> error ("Binary.get(Usage): " ++ show i) +-- | Extract the distinguishing fingerprint carried by a particular 'Usage' +-- constructor. Every constructor stores a hash capturing the bit of state +-- that drives recompilation decisions, so we can sort on it directly. +usageFingerprint :: Usage -> Fingerprint +usageFingerprint UsagePackageModule{ usg_mod_hash = fp } = fp +usageFingerprint UsageHomeModule{ usg_mod_hash = fp } = fp +usageFingerprint UsageFile{ usg_file_hash = fp } = fp +usageFingerprint UsageDirectory{ usg_dir_hash = fp } = fp +usageFingerprint UsageHomeModuleInterface{ usg_iface_hash = fp } = fp +usageFingerprint UsageMergedRequirement{ usg_mod_hash = fp } = fp + -- | Records the imports that we depend on from a home module, -- for recompilation checking. -- ===================================== testsuite/tests/driver/recomp016/recomp016.stdout ===================================== @@ -9,4 +9,4 @@ second run [2 of 5] Compiling B ( B.hs, B.o ) [Source file changed] [3 of 5] Compiling C ( C.hs, C.o ) [B changed] [4 of 5] Compiling D ( D.hs, D.o ) [C changed] -[5 of 5] Compiling E ( E.hs, E.o ) [B changed] +[5 of 5] Compiling E ( E.hs, E.o ) [D changed] View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8201d1baa4a0667052720fcfc127b9b2... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8201d1baa4a0667052720fcfc127b9b2... You're receiving this email because of your account on gitlab.haskell.org.