[Git][ghc/ghc][wip/sjakobi/elem-tests] Improve tests for `elem`
by Simon Jakobi (@sjakobi2) 29 Mar '26
by Simon Jakobi (@sjakobi2) 29 Mar '26
29 Mar '26
Simon Jakobi pushed to branch wip/sjakobi/elem-tests at Glasgow Haskell Compiler / GHC
Commits:
0a50d9ab by Simon Jakobi at 2026-03-29T12:05:43+02:00
Improve tests for `elem`
* Improve T17752 by including the Core output in golden files, checking
all of -O0, -O1 and -O2.
* Add tests for fusion and no-fusion cases.
Fixes #27101.
- - - - -
13 changed files:
- + libraries/base/tests/perf/ElemFusionUnknownList.hs
- + libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr
- + libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr
- + libraries/base/tests/perf/ElemNoFusion.hs
- + libraries/base/tests/perf/ElemNoFusion_O1.stderr
- + libraries/base/tests/perf/ElemNoFusion_O2.stderr
- − libraries/base/tests/perf/Makefile
- libraries/base/tests/perf/T17752.hs
- − libraries/base/tests/perf/T17752.stdout
- + libraries/base/tests/perf/T17752_O0.stderr
- + libraries/base/tests/perf/T17752_O1.stderr
- + libraries/base/tests/perf/T17752_O2.stderr
- libraries/base/tests/perf/all.T
Changes:
=====================================
libraries/base/tests/perf/ElemFusionUnknownList.hs
=====================================
@@ -0,0 +1,21 @@
+-- We expect `elem` to fuse with good producers such as `map`, `concatMap`,
+-- and `filter`.
+module ElemFusionUnknownList where
+
+fusionElemMap :: Int -> [Int] -> Bool
+fusionElemMap x = elem x . map (+1)
+
+fusionNotElemMap :: Int -> [Int] -> Bool
+fusionNotElemMap x = notElem x . map (+1)
+
+fusionElemConcatMap :: Int -> [Int] -> Bool
+fusionElemConcatMap x = elem x . concatMap (\y -> [y + 1, y + 2])
+
+fusionNotElemConcatMap :: Int -> [Int] -> Bool
+fusionNotElemConcatMap x = notElem x . concatMap (\y -> [y + 1, y + 2])
+
+fusionElemFilter :: Int -> [Int] -> Bool
+fusionElemFilter x = elem x . filter odd
+
+fusionNotElemFilter :: Int -> [Int] -> Bool
+fusionNotElemFilter x = notElem x . filter odd
=====================================
libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr
=====================================
@@ -0,0 +1,124 @@
+fusionNotElemFilter
+ = \ x eta ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> True;
+ : y ys ->
+ case y of { I# ipv ->
+ case remInt# ipv 2# of {
+ __DEFAULT ->
+ case x of { I# x1 ->
+ case ==# x1 ipv of {
+ __DEFAULT -> jump go1 ys;
+ 1# -> False
+ }
+ };
+ 0# -> jump go1 ys
+ }
+ }
+ }; } in
+ jump go1 eta
+
+fusionElemFilter
+ = \ x eta ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> False;
+ : y ys ->
+ case y of { I# ipv ->
+ case remInt# ipv 2# of {
+ __DEFAULT ->
+ case x of { I# x1 ->
+ case ==# x1 ipv of {
+ __DEFAULT -> jump go1 ys;
+ 1# -> True
+ }
+ };
+ 0# -> jump go1 ys
+ }
+ }
+ }; } in
+ jump go1 eta
+
+fusionNotElemConcatMap
+ = \ x x1 ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> True;
+ : y ys ->
+ case y of { I# x2 ->
+ case x of { I# x3 ->
+ case ==# x3 (+# x2 1#) of {
+ __DEFAULT ->
+ case ==# x3 (+# x2 2#) of {
+ __DEFAULT -> jump go1 ys;
+ 1# -> False
+ };
+ 1# -> False
+ }
+ }
+ }
+ }; } in
+ jump go1 x1
+
+fusionElemConcatMap
+ = \ x x1 ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> False;
+ : y ys ->
+ case y of { I# x2 ->
+ case x of { I# x3 ->
+ case ==# x3 (+# x2 1#) of {
+ __DEFAULT ->
+ case ==# x3 (+# x2 2#) of {
+ __DEFAULT -> jump go1 ys;
+ 1# -> True
+ };
+ 1# -> True
+ }
+ }
+ }
+ }; } in
+ jump go1 x1
+
+fusionNotElemMap
+ = \ x eta ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> True;
+ : y ys ->
+ case x of { I# x1 ->
+ case y of { I# x2 ->
+ case ==# x1 (+# x2 1#) of {
+ __DEFAULT -> jump go1 ys;
+ 1# -> False
+ }
+ }
+ }
+ }; } in
+ jump go1 eta
+
+fusionElemMap
+ = \ x eta ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> False;
+ : y ys ->
+ case x of { I# x1 ->
+ case y of { I# x2 ->
+ case ==# x1 (+# x2 1#) of {
+ __DEFAULT -> jump go1 ys;
+ 1# -> True
+ }
+ }
+ }
+ }; } in
+ jump go1 eta
+
=====================================
libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr
=====================================
@@ -0,0 +1,206 @@
+fusionNotElemFilter
+ = \ x eta ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> True;
+ : y ys ->
+ case y of { I# ipv ->
+ case remInt# ipv 2# of {
+ __DEFAULT ->
+ case x of { I# x1 ->
+ case ==# x1 ipv of {
+ __DEFAULT ->
+ joinrec {
+ go2 ds1
+ = case ds1 of {
+ [] -> True;
+ : y1 ys1 ->
+ case y1 of { I# ipv1 ->
+ case remInt# ipv1 2# of {
+ __DEFAULT ->
+ case ==# x1 ipv1 of {
+ __DEFAULT -> jump go2 ys1;
+ 1# -> False
+ };
+ 0# -> jump go2 ys1
+ }
+ }
+ }; } in
+ jump go2 ys;
+ 1# -> False
+ }
+ };
+ 0# -> jump go1 ys
+ }
+ }
+ }; } in
+ jump go1 eta
+
+fusionElemFilter
+ = \ x eta ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> False;
+ : y ys ->
+ case y of { I# ipv ->
+ case remInt# ipv 2# of {
+ __DEFAULT ->
+ case x of { I# x1 ->
+ case ==# x1 ipv of {
+ __DEFAULT ->
+ joinrec {
+ go2 ds1
+ = case ds1 of {
+ [] -> False;
+ : y1 ys1 ->
+ case y1 of { I# ipv1 ->
+ case remInt# ipv1 2# of {
+ __DEFAULT ->
+ case ==# x1 ipv1 of {
+ __DEFAULT -> jump go2 ys1;
+ 1# -> True
+ };
+ 0# -> jump go2 ys1
+ }
+ }
+ }; } in
+ jump go2 ys;
+ 1# -> True
+ }
+ };
+ 0# -> jump go1 ys
+ }
+ }
+ }; } in
+ jump go1 eta
+
+fusionNotElemConcatMap
+ = \ x x1 ->
+ case x1 of {
+ [] -> True;
+ : y ys ->
+ case y of { I# x2 ->
+ case x of { I# x3 ->
+ case ==# x3 (+# x2 1#) of {
+ __DEFAULT ->
+ case ==# x3 (+# x2 2#) of {
+ __DEFAULT ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> True;
+ : y1 ys1 ->
+ case y1 of { I# x4 ->
+ case ==# x3 (+# x4 1#) of {
+ __DEFAULT ->
+ case ==# x3 (+# x4 2#) of {
+ __DEFAULT -> jump go1 ys1;
+ 1# -> False
+ };
+ 1# -> False
+ }
+ }
+ }; } in
+ jump go1 ys;
+ 1# -> False
+ };
+ 1# -> False
+ }
+ }
+ }
+ }
+
+fusionElemConcatMap
+ = \ x x1 ->
+ case x1 of {
+ [] -> False;
+ : y ys ->
+ case y of { I# x2 ->
+ case x of { I# x3 ->
+ case ==# x3 (+# x2 1#) of {
+ __DEFAULT ->
+ case ==# x3 (+# x2 2#) of {
+ __DEFAULT ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> False;
+ : y1 ys1 ->
+ case y1 of { I# x4 ->
+ case ==# x3 (+# x4 1#) of {
+ __DEFAULT ->
+ case ==# x3 (+# x4 2#) of {
+ __DEFAULT -> jump go1 ys1;
+ 1# -> True
+ };
+ 1# -> True
+ }
+ }
+ }; } in
+ jump go1 ys;
+ 1# -> True
+ };
+ 1# -> True
+ }
+ }
+ }
+ }
+
+fusionNotElemMap
+ = \ x eta ->
+ case eta of {
+ [] -> True;
+ : y ys ->
+ case x of { I# x1 ->
+ case y of { I# x2 ->
+ case ==# x1 (+# x2 1#) of {
+ __DEFAULT ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> True;
+ : y1 ys1 ->
+ case y1 of { I# x3 ->
+ case ==# x1 (+# x3 1#) of {
+ __DEFAULT -> jump go1 ys1;
+ 1# -> False
+ }
+ }
+ }; } in
+ jump go1 ys;
+ 1# -> False
+ }
+ }
+ }
+ }
+
+fusionElemMap
+ = \ x eta ->
+ case eta of {
+ [] -> False;
+ : y ys ->
+ case x of { I# x1 ->
+ case y of { I# x2 ->
+ case ==# x1 (+# x2 1#) of {
+ __DEFAULT ->
+ joinrec {
+ go1 ds
+ = case ds of {
+ [] -> False;
+ : y1 ys1 ->
+ case y1 of { I# x3 ->
+ case ==# x1 (+# x3 1#) of {
+ __DEFAULT -> jump go1 ys1;
+ 1# -> True
+ }
+ }
+ }; } in
+ jump go1 ys;
+ 1# -> True
+ }
+ }
+ }
+ }
+
=====================================
libraries/base/tests/perf/ElemNoFusion.hs
=====================================
@@ -0,0 +1,14 @@
+-- As of March 2026, we don't expect `elem` to fuse with `sort` or `NonEmpty.toList`.
+-- `elem` isn't even specialized, and performs dictionary-passing, but that may
+-- change: #27096
+module ElemNoFusion where
+
+import Data.List (sort)
+import Data.List.NonEmpty (NonEmpty)
+import qualified Data.List.NonEmpty as NonEmpty
+
+noFusionElemNonEmptyToList :: Int -> NonEmpty Int -> Bool
+noFusionElemNonEmptyToList x = elem x . NonEmpty.toList
+
+noFusionElemSort :: Int -> [Int] -> Bool
+noFusionElemSort x = elem x . sort
=====================================
libraries/base/tests/perf/ElemNoFusion_O1.stderr
=====================================
@@ -0,0 +1,5 @@
+noFusionElemSort = \ x x1 -> elem $fEqInt x (actualSort gtInt x1)
+
+noFusionElemNonEmptyToList
+ = \ x x1 -> case x1 of { :| a1 as -> elem $fEqInt x (: a1 as) }
+
=====================================
libraries/base/tests/perf/ElemNoFusion_O2.stderr
=====================================
@@ -0,0 +1,5 @@
+noFusionElemSort = \ x x1 -> elem $fEqInt x (actualSort gtInt x1)
+
+noFusionElemNonEmptyToList
+ = \ x x1 -> case x1 of { :| a1 as -> elem $fEqInt x (: a1 as) }
+
=====================================
libraries/base/tests/perf/Makefile deleted
=====================================
@@ -1,15 +0,0 @@
-# This Makefile runs the tests using GHC's testsuite framework. It
-# assumes the package is part of a GHC build tree with the testsuite
-# installed in ../../../testsuite.
-
-TOP=../../../../testsuite
-include $(TOP)/mk/boilerplate.mk
-include $(TOP)/mk/test.mk
-
-
-T17752:
- '$(TEST_HC)' $(TEST_HC_OPTS) -O --make T17752 -rtsopts -ddump-simpl -ddump-to-file -dsuppress-uniques -dsuppress-all
- # All occurrences of elem should be optimized away.
- # For strings these should result in loops after inlining foldCString.
- # For lists it should result in a case expression.
- echo $$(grep -A4 "elem" T17752.dump-simpl)
=====================================
libraries/base/tests/perf/T17752.hs
=====================================
@@ -6,7 +6,7 @@ module T17752 where
-- Should compile to a pattern match if the rules fire
isElemList x = x `elem` ['a','b','c']
-isNotElemList x = x `elem` ['x','y','z']
+isNotElemList x = x `notElem` ['x','y','z']
isOneOfThese x = x `elem` [1,2,3,4,5::Int]
isNotOneOfThese x = x `notElem` [1,2,3,4,5::Int]
=====================================
libraries/base/tests/perf/T17752.stdout deleted
=====================================
@@ -1,2 +0,0 @@
-[1 of 1] Compiling T17752 ( T17752.hs, T17752.o )
-
=====================================
libraries/base/tests/perf/T17752_O0.stderr
=====================================
@@ -0,0 +1,47 @@
+isElemList
+ = \ x ->
+ elem
+ $fFoldableList
+ $fEqChar
+ x
+ (: (C# 'a'#) (: (C# 'b'#) (: (C# 'c'#) [])))
+
+isNotElemList
+ = \ x ->
+ notElem
+ $fFoldableList
+ $fEqChar
+ x
+ (: (C# 'x'#) (: (C# 'y'#) (: (C# 'z'#) [])))
+
+isOneOfThese
+ = \ x ->
+ elem
+ $fFoldableList
+ $fEqInt
+ x
+ (: (I# 1#) (: (I# 2#) (: (I# 3#) (: (I# 4#) (: (I# 5#) [])))))
+
+isNotOneOfThese
+ = \ x ->
+ notElem
+ $fFoldableList
+ $fEqInt
+ x
+ (: (I# 1#) (: (I# 2#) (: (I# 3#) (: (I# 4#) (: (I# 5#) [])))))
+
+isElemString
+ = \ x -> elem $fFoldableList $fEqChar x (unpackCString# "foo"#)
+
+isNotElemString
+ = \ x -> notElem $fFoldableList $fEqChar x (unpackCString# "bar"#)
+
+isElemStringUtf
+ = \ x ->
+ elem $fFoldableList $fEqChar x (unpackCStringUtf8# "fo\\195\\182"#)
+
+isNotElemStringUtf
+ = \ x ->
+ notElem
+ $fFoldableList $fEqChar x (unpackCStringUtf8# "b\\195\\164r"#)
+
=====================================
libraries/base/tests/perf/T17752_O1.stderr
=====================================
@@ -0,0 +1,118 @@
+isElemList
+ = \ x ->
+ case x of { C# x1 ->
+ case x1 of {
+ __DEFAULT -> False;
+ 'a'# -> True;
+ 'b'# -> True;
+ 'c'# -> True
+ }
+ }
+
+isNotElemList
+ = \ x ->
+ case x of { C# x1 ->
+ case x1 of {
+ __DEFAULT -> True;
+ 'x'# -> False;
+ 'y'# -> False;
+ 'z'# -> False
+ }
+ }
+
+isOneOfThese
+ = \ x ->
+ case x of { I# x1 ->
+ case x1 of {
+ __DEFAULT -> False;
+ 1# -> True;
+ 2# -> True;
+ 3# -> True;
+ 4# -> True;
+ 5# -> True
+ }
+ }
+
+isNotOneOfThese
+ = \ x ->
+ case x of { I# x1 ->
+ case x1 of {
+ __DEFAULT -> True;
+ 1# -> False;
+ 2# -> False;
+ 3# -> False;
+ 4# -> False;
+ 5# -> False
+ }
+ }
+
+isElemString
+ = \ x ->
+ joinrec {
+ go addr z
+ = case indexCharOffAddr# addr 0# of ch {
+ __DEFAULT ->
+ case x of { C# x1 ->
+ case eqChar# x1 ch of {
+ __DEFAULT -> jump go (plusAddr# addr 1#) z;
+ 1# -> True
+ }
+ };
+ '\NUL'# -> z
+ }; } in
+ jump go isElemString1 False
+
+isNotElemString
+ = \ x ->
+ joinrec {
+ go addr z
+ = case indexCharOffAddr# addr 0# of ch {
+ __DEFAULT ->
+ case x of { C# x1 ->
+ case eqChar# x1 ch of {
+ __DEFAULT -> jump go (plusAddr# addr 1#) z;
+ 1# -> False
+ }
+ };
+ '\NUL'# ->
+ case z of {
+ False -> True;
+ True -> False
+ }
+ }; } in
+ jump go isNotElemString1 False
+
+isElemStringUtf
+ = \ x ->
+ unpackFoldrCStringUtf8#
+ isElemStringUtf1
+ (\ y r ->
+ case x of { C# x1 ->
+ case y of { C# y1 ->
+ case eqChar# x1 y1 of {
+ __DEFAULT -> r;
+ 1# -> True
+ }
+ }
+ })
+ False
+
+isNotElemStringUtf
+ = \ x ->
+ case unpackFoldrCStringUtf8#
+ isNotElemStringUtf1
+ (\ y r ->
+ case x of { C# x1 ->
+ case y of { C# y1 ->
+ case eqChar# x1 y1 of {
+ __DEFAULT -> r;
+ 1# -> True
+ }
+ }
+ })
+ False
+ of {
+ False -> True;
+ True -> False
+ }
+
=====================================
libraries/base/tests/perf/T17752_O2.stderr
=====================================
@@ -0,0 +1,130 @@
+isElemList
+ = \ x ->
+ case x of { C# x1 ->
+ case x1 of {
+ __DEFAULT -> False;
+ 'a'# -> True;
+ 'b'# -> True;
+ 'c'# -> True
+ }
+ }
+
+isNotElemList
+ = \ x ->
+ case x of { C# x1 ->
+ case x1 of {
+ __DEFAULT -> True;
+ 'x'# -> False;
+ 'y'# -> False;
+ 'z'# -> False
+ }
+ }
+
+isOneOfThese
+ = \ x ->
+ case x of { I# x1 ->
+ case x1 of {
+ __DEFAULT -> False;
+ 1# -> True;
+ 2# -> True;
+ 3# -> True;
+ 4# -> True;
+ 5# -> True
+ }
+ }
+
+isNotOneOfThese
+ = \ x ->
+ case x of { I# x1 ->
+ case x1 of {
+ __DEFAULT -> True;
+ 1# -> False;
+ 2# -> False;
+ 3# -> False;
+ 4# -> False;
+ 5# -> False
+ }
+ }
+
+isElemString
+ = \ x ->
+ case indexCharOffAddr# isElemString1 0# of ch {
+ __DEFAULT ->
+ case x of { C# x1 ->
+ case eqChar# x1 ch of {
+ __DEFAULT ->
+ joinrec {
+ go addr z
+ = case indexCharOffAddr# addr 0# of ch1 {
+ __DEFAULT ->
+ case eqChar# x1 ch1 of {
+ __DEFAULT -> jump go (plusAddr# addr 1#) z;
+ 1# -> True
+ };
+ '\NUL'# -> z
+ }; } in
+ jump go (plusAddr# isElemString1 1#) False;
+ 1# -> True
+ }
+ };
+ '\NUL'# -> False
+ }
+
+isNotElemString
+ = \ x ->
+ case indexCharOffAddr# isNotElemString1 0# of ch {
+ __DEFAULT ->
+ case x of { C# x1 ->
+ case eqChar# x1 ch of {
+ __DEFAULT ->
+ joinrec {
+ $sgo sc
+ = case indexCharOffAddr# sc 0# of ch1 {
+ __DEFAULT ->
+ case eqChar# x1 ch1 of {
+ __DEFAULT -> jump $sgo (plusAddr# sc 1#);
+ 1# -> False
+ };
+ '\NUL'# -> True
+ }; } in
+ jump $sgo (plusAddr# isNotElemString1 1#);
+ 1# -> False
+ }
+ };
+ '\NUL'# -> True
+ }
+
+isElemStringUtf
+ = \ x ->
+ unpackFoldrCStringUtf8#
+ isElemStringUtf1
+ (\ y r ->
+ case x of { C# x1 ->
+ case y of { C# y1 ->
+ case eqChar# x1 y1 of {
+ __DEFAULT -> r;
+ 1# -> True
+ }
+ }
+ })
+ False
+
+isNotElemStringUtf
+ = \ x ->
+ case unpackFoldrCStringUtf8#
+ isNotElemStringUtf1
+ (\ y r ->
+ case x of { C# x1 ->
+ case y of { C# y1 ->
+ case eqChar# x1 y1 of {
+ __DEFAULT -> r;
+ 1# -> True
+ }
+ }
+ })
+ False
+ of {
+ False -> True;
+ True -> False
+ }
+
=====================================
libraries/base/tests/perf/all.T
=====================================
@@ -2,10 +2,26 @@
setTestOpts(js_skip)
#--------------------------------------
-# Check specialization of elem via rules
+# Check optimization of `elem`
#--------------------------------------
-test('T17752', [only_ways(['normal'])] , makefile_test, ['T17752'])
+elemCoreFilter = "sed -En '/^(is|fusion|noFusion)[A-Za-z]*($| )/,/^$/p'"
+
+def elemCoreTest(test_name, module_name, opt):
+ test(test_name,
+ [only_ways(['normal']), extra_files([module_name + '.hs'])],
+ multimod_compile_filter,
+ [module_name,
+ f'{opt} -ddump-simpl -dsuppress-all -dsuppress-uniques -dno-typeable-binds',
+ elemCoreFilter])
+
+elemCoreTest('T17752_O0', 'T17752', '-O0')
+elemCoreTest('T17752_O1', 'T17752', '-O1')
+elemCoreTest('T17752_O2', 'T17752', '-O2')
+elemCoreTest('ElemFusionUnknownList_O1', 'ElemFusionUnknownList', '-O1')
+elemCoreTest('ElemFusionUnknownList_O2', 'ElemFusionUnknownList', '-O2')
+elemCoreTest('ElemNoFusion_O1', 'ElemNoFusion', '-O1')
+elemCoreTest('ElemNoFusion_O2', 'ElemNoFusion', '-O2')
#--------------------------------------
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0a50d9abba1f901554f18d1c96b413d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0a50d9abba1f901554f18d1c96b413d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/ani/no-ds-flag-cache] simplify get_Deepsubsumption_flag
by Apoorv Ingle (@ani) 29 Mar '26
by Apoorv Ingle (@ani) 29 Mar '26
29 Mar '26
Apoorv Ingle pushed to branch wip/ani/no-ds-flag-cache at Glasgow Haskell Compiler / GHC
Commits:
578a8de5 by Apoorv Ingle at 2026-03-28T20:33:48-05:00
simplify get_Deepsubsumption_flag
- - - - -
1 changed file:
- compiler/GHC/Tc/Utils/Unify.hs
Changes:
=====================================
compiler/GHC/Tc/Utils/Unify.hs
=====================================
@@ -2075,12 +2075,10 @@ getDeepSubsumptionFlag_DataConHead app_head =
if | user_ds
-> Deep DeepSub
| XExpr (ConLikeTc (RealDataCon {})) <- app_head
- = Deep TopSub
- | HsVar _ f <- app_head
- , isDataConId (unLoc f)
- = Deep TopSub
+ -> Deep TopSub
| otherwise
- = Shallow
+ -> Shallow
+ }
-- | 'tc_sub_type_deep' is where the actual work happens for deep subsumption.
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/578a8de5f6d487277fa6fe6265d50cb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/578a8de5f6d487277fa6fe6265d50cb…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/mangoiv/fix-static-001-darwin] 2 commits: testsuite: ignore stderr of static001
by Magnus (@MangoIV) 29 Mar '26
by Magnus (@MangoIV) 29 Mar '26
29 Mar '26
Magnus pushed to branch wip/mangoiv/fix-static-001-darwin at Glasgow Haskell Compiler / GHC
Commits:
54728e0a by mangoiv at 2026-03-28T18:52:59+01:00
testsuite: ignore stderr of static001
This reactivates the test on x86_64 darwin as this should have been done
long ago and ignores stderr since the warnings emitted by ranlib on
newer version of the darwin toolchain are benign (no symbols for stub
libraries.
Fixes 27116.
- - - - -
30216cc7 by mangoiv at 2026-03-28T18:53:15+01:00
REVERT: only run on beta
- - - - -
3 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- testsuite/tests/driver/all.T
Changes:
=====================================
.gitlab/generate-ci/gen_ci.hs
=====================================
@@ -301,8 +301,8 @@ runnerTag arch (Linux _) =
Amd64 -> "x86_64-linux"
AArch64 -> "aarch64-linux"
I386 -> "x86_64-linux"
-runnerTag AArch64 Darwin = "aarch64-darwin"
-runnerTag Amd64 Darwin = "x86_64-darwin-m1"
+runnerTag AArch64 Darwin = "beta"
+runnerTag Amd64 Darwin = "beta"
runnerTag Amd64 Windows = "new-x86_64-windows"
runnerTag Amd64 FreeBSD14 = "x86_64-freebsd14"
runnerTag _ _ = error "Invalid arch/opsys"
=====================================
.gitlab/jobs.yaml
=====================================
@@ -50,7 +50,7 @@
],
"stage": "full-build",
"tags": [
- "aarch64-darwin"
+ "beta"
],
"variables": {
"BIGNUM_BACKEND": "gmp",
@@ -838,7 +838,7 @@
],
"stage": "full-build",
"tags": [
- "aarch64-darwin"
+ "beta"
],
"variables": {
"BIGNUM_BACKEND": "gmp",
@@ -1638,7 +1638,7 @@
],
"stage": "full-build",
"tags": [
- "x86_64-darwin-m1"
+ "beta"
],
"variables": {
"BIGNUM_BACKEND": "gmp",
@@ -3877,7 +3877,7 @@
],
"stage": "full-build",
"tags": [
- "aarch64-darwin"
+ "beta"
],
"variables": {
"BIGNUM_BACKEND": "gmp",
@@ -4459,7 +4459,7 @@
],
"stage": "full-build",
"tags": [
- "x86_64-darwin-m1"
+ "beta"
],
"variables": {
"BIGNUM_BACKEND": "gmp",
@@ -5561,7 +5561,7 @@
],
"stage": "full-build",
"tags": [
- "x86_64-darwin-m1"
+ "beta"
],
"variables": {
"BIGNUM_BACKEND": "gmp",
=====================================
testsuite/tests/driver/all.T
=====================================
@@ -121,8 +121,7 @@ else:
only_darwin = skip
test('static001', [extra_files(['Static001.hs']),
- only_darwin,
- when(arch('x86_64'), expect_broken(8127))],
+ only_darwin, ignore_stderr],
makefile_test, ['static001'])
test('dynHelloWorld',
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0da808865116bf06a063eeec2c82c7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0da808865116bf06a063eeec2c82c7…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
29 Mar '26
Magnus pushed new branch wip/mangoiv/fix-static-001-darwin at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/mangoiv/fix-static-001-darwin
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/int-index/unify-wc-hole
by Vladislav Zavialov (@int-index) 29 Mar '26
by Vladislav Zavialov (@int-index) 29 Mar '26
29 Mar '26
Vladislav Zavialov pushed new branch wip/int-index/unify-wc-hole at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/int-index/unify-wc-hole
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc] Pushed new branch wip/mangoiv/allow-metric-decrease-i386
by Magnus (@MangoIV) 28 Mar '26
by Magnus (@MangoIV) 28 Mar '26
28 Mar '26
Magnus pushed new branch wip/mangoiv/allow-metric-decrease-i386 at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/mangoiv/allow-metric-decrease…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T27106] Fix -dsuppress-uniques for free variables in demand signatures
by Simon Jakobi (@sjakobi2) 28 Mar '26
by Simon Jakobi (@sjakobi2) 28 Mar '26
28 Mar '26
Simon Jakobi pushed to branch wip/sjakobi/T27106 at Glasgow Haskell Compiler / GHC
Commits:
6a7faadc by Simon Jakobi at 2026-03-28T12:58:05+01:00
Fix -dsuppress-uniques for free variables in demand signatures
Before: Str=b{sXyZ->S}
With this patch: Str=b{S}
T13143.stderr is updated accordingly.
Fixes #27106.
- - - - -
5 changed files:
- compiler/GHC/Types/Demand.hs
- testsuite/tests/dmdanal/should_compile/T13143.stderr
- + testsuite/tests/dmdanal/should_compile/T27106.hs
- + testsuite/tests/dmdanal/should_compile/T27106.stderr
- testsuite/tests/dmdanal/should_compile/all.T
Changes:
=====================================
compiler/GHC/Types/Demand.hs
=====================================
@@ -2830,7 +2830,10 @@ instance Outputable DmdEnv where
= ppr div <> if null fv_elts then empty
else braces (fsep (map pp_elt fv_elts))
where
- pp_elt (uniq, dmd) = ppr uniq <> text "->" <> ppr dmd
+ pp_elt (uniq, dmd) =
+ sdocOption sdocSuppressUniques $ \case
+ True -> ppr dmd
+ False -> ppr uniq <> text "->" <> ppr dmd
fv_elts = nonDetUFMToList fvs
-- It's OK to use nonDetUFMToList here because we only do it for
-- pretty printing
=====================================
testsuite/tests/dmdanal/should_compile/T13143.stderr
=====================================
@@ -1,13 +1,13 @@
==================== Tidy Core ====================
Result size of Tidy Core
- = {terms: 71, types: 40, coercions: 0, joins: 0/0}
+ = {terms: 59, types: 31, coercions: 0, joins: 0/0}
Rec {
-- RHS size: {terms: 4, types: 3, coercions: 0, joins: 0/0}
T13143.$wf [InlPrag=NOINLINE, Occ=LoopBreaker]
:: forall a. (# #) -> a
-[GblId, Arity=1, Str=<B>b{sBX->S}, Cpr=b, Unf=OtherCon []]
+[GblId, Arity=1, Str=<B>b{S}, Cpr=b, Unf=OtherCon []]
T13143.$wf
= \ (@a) _ [Occ=Dead] -> T13143.$wf @a GHC.Internal.Types.(##)
end Rec }
@@ -16,7 +16,7 @@ end Rec }
f [InlPrag=NOINLINE[final]] :: forall a. Int -> a
[GblId,
Arity=1,
- Str=<B>b{sBX->S},
+ Str=<B>b{S},
Cpr=b,
Unf=Unf{Src=StableSystem, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
@@ -26,100 +26,58 @@ f [InlPrag=NOINLINE[final]] :: forall a. Int -> a
f = \ (@a) _ [Occ=Dead] -> T13143.$wf @a GHC.Internal.Types.(##)
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T13143.$trModule4 :: GHC.Internal.Prim.Addr#
-[GblId,
- Unf=Unf{Src=<vanilla>, TopLvl=True,
- Value=True, ConLike=True, WorkFree=True, Expandable=True,
- Guidance=IF_ARGS [] 20 0}]
-T13143.$trModule4 = "main"#
+$trModule1 :: GHC.Internal.Prim.Addr#
+[GblId, Unf=OtherCon []]
+$trModule1 = "main"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T13143.$trModule3 :: GHC.Internal.Types.TrName
-[GblId,
- Unf=Unf{Src=<vanilla>, TopLvl=True,
- Value=True, ConLike=True, WorkFree=True, Expandable=True,
- Guidance=IF_ARGS [] 10 10}]
-T13143.$trModule3 = GHC.Internal.Types.TrNameS T13143.$trModule4
+$trModule2 :: GHC.Internal.Types.TrName
+[GblId, Unf=OtherCon []]
+$trModule2 = GHC.Internal.Types.TrNameS $trModule1
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T13143.$trModule2 :: GHC.Internal.Prim.Addr#
-[GblId,
- Unf=Unf{Src=<vanilla>, TopLvl=True,
- Value=True, ConLike=True, WorkFree=True, Expandable=True,
- Guidance=IF_ARGS [] 30 0}]
-T13143.$trModule2 = "T13143"#
+$trModule3 :: GHC.Internal.Prim.Addr#
+[GblId, Unf=OtherCon []]
+$trModule3 = "T13143"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T13143.$trModule1 :: GHC.Internal.Types.TrName
-[GblId,
- Unf=Unf{Src=<vanilla>, TopLvl=True,
- Value=True, ConLike=True, WorkFree=True, Expandable=True,
- Guidance=IF_ARGS [] 10 10}]
-T13143.$trModule1 = GHC.Internal.Types.TrNameS T13143.$trModule2
+$trModule4 :: GHC.Internal.Types.TrName
+[GblId, Unf=OtherCon []]
+$trModule4 = GHC.Internal.Types.TrNameS $trModule3
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-T13143.$trModule :: GHC.Internal.Types.Module
-[GblId,
- Unf=Unf{Src=<vanilla>, TopLvl=True,
- Value=True, ConLike=True, WorkFree=True, Expandable=True,
- Guidance=IF_ARGS [] 10 10}]
-T13143.$trModule
- = GHC.Internal.Types.Module T13143.$trModule3 T13143.$trModule1
+T13143.$trModule [InlPrag=[~]] :: GHC.Internal.Types.Module
+[GblId, Unf=OtherCon []]
+T13143.$trModule = GHC.Internal.Types.Module $trModule2 $trModule4
--- RHS size: {terms: 2, types: 1, coercions: 0, joins: 0/0}
+-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
lvl :: Int
-[GblId, Str=b{sBX->S}, Cpr=b]
-lvl = T13143.$wf @Int GHC.Internal.Types.(##)
+[GblId, Unf=OtherCon []]
+lvl = GHC.Internal.Types.I# 1#
+
+-- RHS size: {terms: 2, types: 1, coercions: 0, joins: 0/0}
+lvl1 :: Int
+[GblId, Str=b{S}, Cpr=b]
+lvl1 = T13143.$wf @Int GHC.Internal.Types.(##)
Rec {
-- RHS size: {terms: 28, types: 7, coercions: 0, joins: 0/0}
-T13143.$wg [InlPrag=[2], Occ=LoopBreaker]
- :: Bool -> Bool -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int#
-[GblId[StrictWorker([!, !])],
- Arity=3,
- Str=<1L><1L><L>,
- Unf=OtherCon []]
-T13143.$wg
- = \ (ds :: Bool) (ds1 :: Bool) (ww :: GHC.Internal.Prim.Int#) ->
+g [Occ=LoopBreaker] :: Bool -> Bool -> Int -> Int
+[GblId, Arity=3, Str=<1L><1L><L>, Unf=OtherCon []]
+g = \ (ds :: Bool) (ds1 :: Bool) (p :: Int) ->
case ds of {
False ->
case ds1 of {
- False ->
- T13143.$wg GHC.Internal.Types.False GHC.Internal.Types.True ww;
- True -> GHC.Internal.Prim.+# ww 1#
+ False -> g GHC.Internal.Types.False GHC.Internal.Types.True p;
+ True -> + @Int GHC.Internal.Num.$fNumInt p lvl
};
True ->
case ds1 of {
- False ->
- T13143.$wg GHC.Internal.Types.True GHC.Internal.Types.True ww;
- True -> case lvl of {}
+ False -> g GHC.Internal.Types.True GHC.Internal.Types.True p;
+ True -> lvl1
}
}
end Rec }
--- RHS size: {terms: 14, types: 6, coercions: 0, joins: 0/0}
-g [InlPrag=[2]] :: Bool -> Bool -> Int -> Int
-[GblId,
- Arity=3,
- Str=<1L><1L><1!P(L)>,
- Cpr=1,
- Unf=Unf{Src=StableSystem, TopLvl=True,
- Value=True, ConLike=True, WorkFree=True, Expandable=True,
- Guidance=ALWAYS_IF(arity=3,unsat_ok=True,boring_ok=False)
- Tmpl= \ (ds [Occ=Once1] :: Bool)
- (ds1 [Occ=Once1] :: Bool)
- (p [Occ=Once1!] :: Int) ->
- case p of { GHC.Internal.Types.I# ww [Occ=Once1] ->
- case T13143.$wg ds ds1 ww of ww1 [Occ=Once1] { __DEFAULT ->
- GHC.Internal.Types.I# ww1
- }
- }}]
-g = \ (ds :: Bool) (ds1 :: Bool) (p :: Int) ->
- case p of { GHC.Internal.Types.I# ww ->
- case T13143.$wg ds ds1 ww of ww1 { __DEFAULT ->
- GHC.Internal.Types.I# ww1
- }
- }
-
=====================================
testsuite/tests/dmdanal/should_compile/T27106.hs
=====================================
@@ -0,0 +1,5 @@
+module T27106 where
+
+{-# NOINLINE weird #-}
+weird :: Int -> a
+weird x = weird x
=====================================
testsuite/tests/dmdanal/should_compile/T27106.stderr
=====================================
@@ -0,0 +1,4 @@
+weird [InlPrag=NOINLINE[final]] :: forall a. Int -> a
+[GblId,
+ Arity=1,
+ Str=<B>b{S},
=====================================
testsuite/tests/dmdanal/should_compile/all.T
=====================================
@@ -45,6 +45,13 @@ test('T13077a', normal, compile, [''])
# T13143: WW for NOINLINE function f
test('T13143', [ grep_errmsg(r'^T13143\.\$wf') ], compile, ['-ddump-simpl -dsuppress-uniques'])
+# Uniques in the free variable part of a demand signature should be
+# suppressed by -dsuppress-uniques.
+test('T27106', normal, multimod_compile_filter,
+ ['T27106',
+ '-v0 -O -ddump-simpl -dsuppress-uniques',
+ r"sed -n '/^weird /,/.* Str=/p'"])
+
# T15627
# Absent bindings of unlifted types should be WW'ed away.
# The idea is to check that both $wmutVar and $warray
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6a7faadcbe78ad826ab116b6191c7d0…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6a7faadcbe78ad826ab116b6191c7d0…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T27115] Various notation fixes regarding demand signatures
by Simon Jakobi (@sjakobi2) 28 Mar '26
by Simon Jakobi (@sjakobi2) 28 Mar '26
28 Mar '26
Simon Jakobi pushed to branch wip/sjakobi/T27115 at Glasgow Haskell Compiler / GHC
Commits:
bb4800ff by Simon Jakobi at 2026-03-28T12:40:29+01:00
Various notation fixes regarding demand signatures
- - - - -
2 changed files:
- compiler/GHC/Types/Demand.hs
- docs/users_guide/using-optimisation.rst
Changes:
=====================================
compiler/GHC/Types/Demand.hs
=====================================
@@ -510,7 +510,7 @@ type CardNonOnce = Card
-- | Absent, {0}. Pretty-printed as A.
pattern C_00 :: Card
pattern C_00 = Card 0b001
--- | Bottom, {}. Pretty-printed as A.
+-- | Bottom, {}. Pretty-printed as B.
pattern C_10 :: Card
pattern C_10 = Card 0b000
-- | Strict and used once, {1}. Pretty-printed as 1.
@@ -2046,7 +2046,7 @@ gets reached. For example, we don't want to be strict in the strict free
variables of 'rhs'.
So we have the simple definition
- deferAfterPreciseException = lubDmdType (DmdType emptyDmdEnv [] exnDiv)
+ deferAfterPreciseException = lubDmdType (DmdType (DE emptyVarEnv exnDiv) [])
Historically, when we had `lubBoxity = _unboxedWins` (see Note [unboxedWins]),
we had a more complicated definition for deferAfterPreciseException to make sure
@@ -2054,7 +2054,7 @@ it preserved boxity in its argument. That was needed for code like
case <I/O operation> of
(# s', r) -> f x
-which uses `x` *boxed*. If we `lub`bed it with `(DmdType emptyDmdEnv [] exnDiv)`
+which uses `x` *boxed*. If we `lub`bed it with `(DmdType (DE emptyVarEnv exnDiv) [])`
we'd get an *unboxed* demand on `x` (because we let Unboxed win),
which led to #20746. Nowadays with `lubBoxity = boxedWins` we don't need
the complicated definition.
@@ -2191,12 +2191,12 @@ transformer, namely
a single DmdType
(Nevertheless we dignify DmdSig as a distinct type.)
-The DmdSig for an Id is a semantic thing. Suppose a function `f` has a DmdSig of
- DmdSig (DmdType (fv_dmds,res) [d1..dn])
+The DmdSig for an Id is a semantic thing. Suppose a function `f` has a DmdSig of
+ DmdSig (DmdType (DmdEnv fv_dmds div) [d1..dn])
Here `n` is called the "demand-sig arity" of the DmdSig. The signature means:
* If you apply `f` to n arguments (the demand-sig-arity)
* then you can unleash demands d1..dn on the arguments
- * and demands fv_dmds on the free variables.
+ * and the demands fv_dmds on the free variables.
Also see Note [Demand type Divergence] for the meaning of a Divergence in a
demand signature.
@@ -2206,10 +2206,10 @@ demand, used for signature inference. Therefore we place a top demand on all
arguments.
For example, the demand transformer described by the demand signature
- DmdSig (DmdType {x -> <1L>} <A><1P(L,L)>)
+ <A><1P(L,L)>{x->1L}
says that when the function is applied to two arguments, it
-unleashes demand 1L on the free var x, A on the first arg,
-and 1P(L,L) on the second.
+unleashes demand A on the first arg, 1P(L,L) on the second,
+and 1L on the free var x.
If this same function is applied to one arg, all we can say is that it
uses x with 1L, and its arg with demand 1P(L,L).
@@ -2229,10 +2229,10 @@ was evaluated. Here's an example:
The abstract transformer (let's call it F_e) of the if expression (let's
call it e) would transform an incoming (undersaturated!) head sub-demand A
-into a demand type like {x-><1L>,y-><L>}<L>. In pictures:
+into a demand type like <L>{x->1L,y->L}. In pictures:
SubDemand ---F_e---> DmdType
- <A> {x-><1L>,y-><L>}<L>
+ <A> <L>{x->1L,y->L}
Let's assume that the demand transformers we compute for an expression are
correct wrt. to some concrete semantics for Core. How do demand signatures fit
@@ -2240,7 +2240,7 @@ in? They are strange beasts, given that they come with strict rules when to
it's sound to unleash them.
Fortunately, we can formalise the rules with Galois connections. Consider
-f's strictness signature, {}<1L><L>. It's a single-point approximation of
+f's strictness signature, <1L><L>. It's a single-point approximation of
the actual abstract transformer of f's RHS for arity 2. So, what happens is that
we abstract *once more* from the abstract domain we already are in, replacing
the incoming Demand by a simple lattice with two elements denoting incoming
@@ -2260,8 +2260,8 @@ With
and F_f being the abstract transformer of f's RHS and f_f being the abstracted
abstract transformer computable from our demand signature simply by
- f_f(>=2) = {}<1L><L>
- f_f(<2) = multDmdType C_0N {}<1L><L>
+ f_f(>=2) = <1L><L>
+ f_f(<2) = multDmdType C_0N <1L><L>
where multDmdType makes a proper top element out of the given demand type.
@@ -2283,9 +2283,9 @@ yields a more precise demand type:
incoming sub-demand | demand type
--------------------------------
- P(A) | <L><L>{}
- C(1,C(1,P(L))) | <1P(L)><L>{}
- C(1,C(1,1P(1P(L),A))) | <1P(A)><A>{}
+ P(A) | <L><L>
+ C(1,C(1,P(L))) | <1P(L)><L>
+ C(1,C(1,1P(1P(L),A))) | <1P(A)><A>
Note that in the first example, the depth of the demand type was *higher* than
the arity of the incoming call demand due to the anonymous lambda.
=====================================
docs/users_guide/using-optimisation.rst
=====================================
@@ -1614,7 +1614,7 @@ as such you shouldn't need to set any of them explicitly. A flag
a polymorphic sub-demand of the same letter: E.g. ``L`` is equivalent to
``LL`` by expansion of the single letter demand, which is equivalent to
``LP(LP(..))``, so ``L``\s all the way down. It is always clear from
- context whether we talk about about a cardinality, sub-demand or demand.
+ context whether we talk about a cardinality, sub-demand or demand.
**Demand signatures**
@@ -1653,8 +1653,8 @@ as such you shouldn't need to set any of them explicitly. A flag
maybe n _ Nothing = n
maybe _ s (Just a) = s a
- We give it demand signature ``<L><MC(M,L)><1L>``. The ``C(M,L)`` is a *call
- sub-demand* that says "Called at most once, where the result is used
+ We give it demand signature ``<ML><MC(1,L)><1L>``. The ``C(1,L)`` is a *call
+ sub-demand* that says "Called exactly once, where the result is used
according to ``L``". The expression ``f `seq` f 1`` puts ``f`` under
demand ``SC(1,L)`` and serves as an example where the upper bound on
evaluation cardinality doesn't coincide with that of the call cardinality.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bb4800ff7a950000fd428d50fbb44c5…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bb4800ff7a950000fd428d50fbb44c5…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T13960] 37 commits: Check that shift values are valid
by Simon Jakobi (@sjakobi2) 28 Mar '26
by Simon Jakobi (@sjakobi2) 28 Mar '26
28 Mar '26
Simon Jakobi pushed to branch wip/sjakobi/T13960 at Glasgow Haskell Compiler / GHC
Commits:
aa5dfe67 by Sylvain Henry at 2026-03-26T03:48:56-04:00
Check that shift values are valid
In GHC's codebase in non-DEBUG builds we silently substitute shiftL/R
with unsafeShiftL/R for performance reasons. However we were not
checking that the shift value was valid for unsafeShiftL/R, leading to
wrong computations, but only in non-DEBUG builds.
This patch adds the necessary checks and reports an error when a wrong
shift value is passed.
- - - - -
c8a7b588 by Sylvain Henry at 2026-03-26T03:48:56-04:00
Implement basic value range analysis (#25718)
Perform basic value range analysis to try to determine at compile time
the result of the application of some comparison primops (ltWord#, etc.).
This subsumes the built-in rewrite rules used previously to check if one
of the comparison argument was a bound (e.g. (x :: Word8) <= 255 is
always True). Our analysis is more powerful and handles type
conversions: e.g. word8ToWord x <= 255 is now detected as always True too.
We also use value range analysis to filter unreachable alternatives in
case-expressions. To support this, we had to allow case-expressions for
primitive types to not have a DEFAULT alternative (as was assumed before
and checked in Core lint).
- - - - -
a5ec467e by ARATA Mizuki at 2026-03-26T03:49:49-04:00
rts: Align stack to 64-byte boundary in StgRun on x86
When LLVM spills AVX/AVX-512 vector registers to the stack, it requires
32-byte (__m256) or 64-byte (__m512) alignment. If the stack is not
sufficiently aligned, LLVM inserts a realignment prologue that reserves
%rbp as a frame pointer, conflicting with GHC's use of %rbp as an STG
callee-saved register and breaking the tail-call-based calling convention.
Previously, GHC worked around this by lying to LLVM about the stack
alignment and rewriting aligned vector loads/stores (VMOVDQA, VMOVAPS)
to unaligned ones (VMOVDQU, VMOVUPS) in the LLVM Mangler. This had two
problems:
- It did not extend to AVX-512, which requires 64-byte alignment. (#26595)
- When Haskell calls a C function that takes __m256/__m512 arguments on
the stack, the callee requires genuine alignment, which could cause a
segfault. (#26822)
This patch genuinely aligns the stack to 64 bytes in StgRun by saving
the original stack pointer before alignment and restoring it in
StgReturn. We now unconditionally advertise 64-byte stack alignment to
LLVM for all x86 targets, making rewriteAVX in the LLVM Mangler
unnecessary. STG_RUN_STACK_FRAME_SIZE is increased from 48 to 56 bytes
on non-Windows x86-64 to store the saved stack pointer.
Closes #26595 and #26822
Co-Authored-By: Claude Opus 4.5 <noreply(a)anthropic.com>
- - - - -
661da815 by Teo Camarasu at 2026-03-26T03:50:33-04:00
ghc-internal: Float Generics to near top of module graph
We remove GHC.Internal.Generics from the critical path of the
`ghc-internal` module graph. GHC.Internal.Generics used to be in the
middle of the module graph, but now it is nearer the top (built later).
This change thins out the module graph and allows us to get rid of the
ByteOrder hs-boot file.
We implement this by moving Generics instances from the module where the
datatype is defined to the GHC.Internal.Generics module. This trades off
increasing the compiled size of GHC.Internal.Generics with reducing the
dependency footprint of datatype modules.
Not all instances are moved to GHC.Internal.Generics. For instance,
`GHC.Internal.Control.Monad.Fix` keeps its instance as it is one of the
very last modules compiled in `ghc-internal` and so inverting the
relationship here would risk adding GHC.Internal.Generics back onto the
critical path.
We also don't change modules that are re-exported from the `template-haskell` or `ghc-heap`.
This is done to make it easy to eventually move `Generics` to `base`
once something like #26657 is implemented.
Resolves #26930
Metric Decrease:
T21839c
- - - - -
45428f88 by sheaf at 2026-03-26T03:51:31-04:00
Avoid infinite loop in deep subsumption
This commit ensures we only unify after we recur in the deep subsumption
code in the FunTy vs non-FunTy case of GHC.Tc.Utils.Unify.tc_sub_type_deep,
to avoid falling into an infinite loop.
See the new Wrinkle [Avoiding a loop in tc_sub_type_deep] in
Note [FunTy vs non-FunTy case in tc_sub_type_deep] in GHC.Tc.Utils.Unify.
Fixes #26823
Co-authored-by: simonpj <simon.peytonjones(a)gmail.com>
- - - - -
2823b039 by Ian Duncan at 2026-03-26T03:52:21-04:00
AArch64: fix MOVK regUsageOfInstr to mark dst as both read and written
MOVK (move with keep) modifies only a 16-bit slice of the destination
register, so the destination is both read and written. The register
allocator must know this to avoid clobbering live values. Update
regUsageOfInstr to list the destination in both src and dst sets.
No regression test: triggering the misallocation requires specific
register pressure around a MOVK sequence, which is difficult to
reliably provoke from Haskell source.
- - - - -
57b7878d by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #12002
Closes #12002.
- - - - -
c8f9df2d by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #12046
Closes #12046.
Co-authored-by: Andreas Klebinger <klebinger.andreas(a)gmx.at>
- - - - -
615d72ac by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #13180
Closes #13180.
- - - - -
423eebcf by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #11141
Closes #11141.
- - - - -
286849a4 by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #11505
Closes #11505.
- - - - -
7db149d9 by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression perf test for #13820
Closes #13820.
- - - - -
e73c4adb by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #10381
Closes #10381.
- - - - -
5ebcfb57 by Benjamin Maurer at 2026-03-26T03:54:02-04:00
Generate assembly on x86 for word2float (#22252)
We used to emit C function call for MO_UF_Conv primitive.
Now emits direct assembly instead.
Co-Authored-By: Sylvain Henry <sylvain(a)haskus.fr>
Co-Authored-By: Claude Sonnet 4.6 <noreply(a)anthropic.com>
- - - - -
5b550754 by Matthew Pickering at 2026-03-26T03:54:51-04:00
rts: forward clone-stack messages after TSO migration
MSG_CLONE_STACK assumed that the target TSO was still owned by the
capability that received the message. This is not always true: the TSO
can migrate before the inbox entry is handled.
When that happened, handleCloneStackMessage could clone a live stack from
the wrong capability and use the wrong capability for allocation and
performTryPutMVar, leading to stack sanity failures such as
checkStackFrame: weird activation record found on stack.
Fix this by passing the current capability into
handleCloneStackMessage, rechecking msg->tso->cap at handling time, and
forwarding the message if the TSO has migrated. Once ownership matches,
use the executing capability consistently for cloneStack, rts_apply, and
performTryPutMVar.
Fixes #27008
- - - - -
ef0a1bd2 by mangoiv at 2026-03-26T03:55:34-04:00
release tracking: adopt release tracking ticket from #16816
- - - - -
a7f40fd9 by mangoiv at 2026-03-26T03:55:34-04:00
release tracking: add a release tracking ticket
Brings the information in the release tracking ticket up to date with
https://gitlab.haskell.org/ghc/ghc-hq/-/blob/main/release-management.mkd
Resolves #26691
- - - - -
161d3285 by Teo Camarasu at 2026-03-26T03:56:18-04:00
Revert "Set default eventlog-flush-interval to 5s"
Flushing the eventlog forces a synchronisation of all the capabilities
and there was a worry that this might lead to a performance cost for
some highly parallel workloads.
This reverts commit 66b96e2a591d8e3d60e74af3671344dfe4061cf2.
- - - - -
36eed985 by Cheng Shao at 2026-03-26T03:57:03-04:00
ghc-boot: move GHC.Data.SmallArray to ghc-boot
This commit moves `GHC.Data.SmallArray` from the `ghc` library to
`ghc-boot`, so that it can be used by `ghci` as well:
- The `Binary` (from `ghc`) instance of `SmallArray` is moved to
`GHC.Utils.Binary`
- Util functions `replicateSmallArrayIO`, `mapSmallArrayIO`,
`mapSmallArrayM_`, `imapSmallArrayM_` , `smallArrayFromList` and
`smallArrayToList` are added
- The `Show` instance is added
- The `Binary` (from `binary`) instance is added
- - - - -
fdf828ae by Cheng Shao at 2026-03-26T03:57:03-04:00
compiler: use `Binary` instance of `BCOByteArray` for bytecode objects
This commit defines `Binary` (from `compiler`) instance of
`BCOByteArray` which serializes the underlying buffer directly, and
uses it directly in bytecode object serialization. Previously we reuse
the `Binary` (from `binary`) instance, and this change allows us to
avoid double-copying via an intermediate `ByteString` when using
`put`/`get` in `binnary`. Also see added comment for explanation.
- - - - -
3bf62d0a by Cheng Shao at 2026-03-26T03:57:03-04:00
ghci: use SmallArray directly in ResolvedBCO
This patch makes ghci use `SmallArray` directly in `ResolvedBCO` when
applicable, making the memory representation more compact and reducing
marshaling overhead. Closes #27058.
- - - - -
3d6492ce by Wen Kokke at 2026-03-26T03:57:53-04:00
Fix race condition between flushEventLog and start/endEventLogging.
This commit changes `flushEventLog` to acquire/release the `state_change` mutex to prevent interleaving with `startEventLogging` and `endEventLogging`. In the current RTS, `flushEventLog` _does not_ acquire this mutex, which may lead to eventlog corruption on the following interleaving:
- `startEventLogging` writes the new `EventLogWriter` to `event_log_writer`.
- `flushEventLog` flushes some events to `event_log_writer`.
- `startEventLogging` writes the eventlog header to `event_log_writer`.
This causes the eventlog to be written out in an unreadable state, with one or more events preceding the eventlog header.
This commit renames the old function to `flushEventLog_` and defines `flushEventLog` simply as:
```c
void flushEventLog(Capability **cap USED_IF_THREADS)
{
ACQUIRE_LOCK(&state_change_mutex);
flushEventLog_(cap);
RELEASE_LOCK(&state_change_mutex);
}
```
The old function is still needed internally within the compilation unit, where it is used in `endEventLogging` in a context where the `state_change` mutex has already been acquired. I've chosen to mark `flushEventLog_` as static and let other uses of `flushEventLog` within the RTS refer to the new version. There is one use in `hs_init_ghc` via `flushTrace`, where the new locking behaviour should be harmless, and one use in `handle_tick`, which I believe was likely vulnerable to the same race condition, so the new locking behaviour is desirable.
I have not added a test. The behaviour is highly non-deterministic and requires a program that concurrently calls `flushEventLog` and `startEventLogging`/`endEventLogging`. I encountered the issue while developing `eventlog-socket` and within that context have verified that my patch likely addresses the issue: a test that used to fail within the first dozen or so runs now has been running on repeat for several hours.
- - - - -
7b9a75f0 by Phil Hazelden at 2026-03-26T03:58:37-04:00
Fix build with werror on glibc 2.43.
We've been defining `_XOPEN_SOURCE` and `_POSIX_C_SOURCE` to the same
values as defined in glibc prior to 2.43. But in 2.43, glibc changes
them to new values, which means we get a warning when redefining them.
By `#undef`ing them first, we no longer get a warning.
Closes #27076.
- - - - -
fe6e76c5 by Tobias Haslop at 2026-03-26T03:59:30-04:00
Fix broken Haddock link to Bifunctor class in description of Functor class
- - - - -
404b71c1 by Luite Stegeman at 2026-03-27T04:40:49-04:00
Fix assert in Interpreter.c
If we skip exactly the number of words on the stack we end up on
the first word in the next chunk.
- - - - -
a85bd503 by Luite Stegeman at 2026-03-27T04:40:49-04:00
Support arbitrary size unboxed tuples in bytecode
This stores the size (number of words on the stack) of the next
expected tuple in the TSO, ctoi_spill_size field, eliminating
the need of stg_ctoi_tN frames for each size.
Note: On 32 bit platform there is still a bytecode tuple size
limit of 255 words on the stack.
Fixes #26946
- - - - -
e2209031 by Luite Stegeman at 2026-03-27T04:40:49-04:00
Add specialized frames for small tuples
Small tuples are now returned more efficiently to the interpreter.
They use one less word of stack space and don't need manipulation
of the TSO anymore.
- - - - -
b26bb2ea by VeryMilkyJoe at 2026-03-27T04:41:38-04:00
Remove backwards compatibility pattern synonym `ModLocation`
Fixes #24932
- - - - -
66e5e324 by Vladislav Zavialov at 2026-03-27T04:42:25-04:00
Extend HsExpr with the StarIsType syntax (#26587, #26967)
This patch allows kinds of the form `k -> *` and `* -> k` to occur in
expression syntax, i.e. to be used as required type arguments.
For example:
{-# LANGUAGE RequiredTypeArguments, StarIsType #-}
x1 = f (* -> * -> *)
x2 = f (forall k. k -> *)
x3 = f ((* -> *) -> Constraint)
Summary of the changes:
* Introduce the HsStar constructor of HsExpr and its extension field XStar.
It is analogous to HsStarTy in HsType.
* Refactor HsStarTy to store the unicode flag as TokStar, defined as
type TokStar = EpUniToken "*" "★" -- similar to TokForall, TokRArrow, etc.
The token is stored in the extension field and replaces the Bool field.
* Extend the `infixexp2` nonterminal to parse `*` as a direct argument of `->`.
This is more limited than the full StarIsType syntax, but has the nice
property of not conflicting with the multiplication operator `a * b`.
Test case: T26967 T26967_tyop
- - - - -
f8de456f by Sylvain Henry at 2026-03-27T04:43:22-04:00
STM: don't create a transaction in the rhs of catchRetry# (#26028)
We don't need to create a transaction for the rhs of (catchRetry#)
because contrary to the lhs we don't need to abort it on retry. Moreover
it is particularly harmful if we have code such as (#26028):
let cN = readTVar vN >> retry
tree = c1 `orElse` (c2 `orElse` (c3 `orElse` ...))
atomically tree
Because it will stack transactions for the rhss and the read-sets of all
the transactions will be iteratively merged in O(n^2) after the
execution of the most nested retry.
This is the second attempt at implementing this. The first attempt
triggered segfaults (#26291) and has been reverted.
Co-Authored-By: Claude Sonnet 4.6 <noreply(a)anthropic.com>
- - - - -
fcf092dd by Luite Stegeman at 2026-03-27T04:44:17-04:00
Windows: remove StgAsyncIOResult and fix crash/leaks
In stg_block_async{_void}, a stack slot was reserved for
an StgAsyncIOResult. This slot would be filled by the IO
manager upon completion of the async call.
However, if the blocked thread was interrupted by an async
exception, we would end up in an invalid state:
- If the blocked computation was never re-entered, the
StgAsyncIOResult would never be freed.
- If the blocked computation was re-entered, the thread would
find an unitialized stack slot for the StgAsyncIOResult,
leading to a crash reading its fields, or freeing the pointer.
We fix this by removing the StgAsyncIOResult altogether and writing
the result directly to the stack.
Fixes #26341
- - - - -
05094993 by Luite Stegeman at 2026-03-27T04:45:12-04:00
Don't refine DEFAULT alt for unary typeclasses
A non-DEFAULT data alt for a unary typeclass dictionary would
interfere with Unary Class Magic, leading to segfaults.
fixes #27071
- - - - -
4ee260cf by sheaf at 2026-03-27T04:46:06-04:00
Fix several oversights in hsExprType
This commit fixes several oversights in GHC.Hs.Syn.Type.hsExprType:
- The 'RecordCon' case was returning the type of the constructor,
instead of the constructor application. This is fixed by using
'splitFunTys'.
- The 'ExplicitTuple' case failed to take into account tuple sections,
and was also incorrectly handling 1-tuples (e.g. 'Solo') which can
be constructed using Template Haskell.
- The 'NegApp' case was returning the type of the negation operator,
again failing to apply it to the argument. Fixed by using
'funResultTy'.
- The 'HsProc' case was computing the result type of the arrow proc
block, without taking into account the argument type. Fix that by
adding a new field to 'CmdTopTc' that stores the arrow type, so that
we can construct the correct result type `arr a b` for
`proc (pat :: a) -> (cmd :: b)`.
- The 'ArithSeq' and 'NegApp' cases were failing to take into account
the result 'HsWrapper', which could e.g. silently drop casts.
This is fixed by introducing 'syntaxExpr_wrappedFunResTy' which, on
top of taking the result type, applies the result 'HsWrapper'.
These fixes are validated by the new GHC API test T26910.
Fixes #26910
- - - - -
e97232ce by Hai at 2026-03-27T04:47:04-04:00
Parser.y: avoid looking at token with QualifiedDo
This changes the behavior of 'hintQualifiedDo' so that the supplied
token is not inspected when the QualifiedDo language extension bit is
set.
- - - - -
9831385b by Vladislav Zavialov at 2026-03-27T17:22:30-04:00
Infix holes in types (#11107)
This patch introduces several improvements that follow naturally from
refactoring HsOpTy to represent the operator as an HsType, aligning it
with the approach taken by OpApp and HsExpr.
User-facing changes:
1. Infix holes (t1 `_` t2) are now permitted in types, following the
precedent set by term-level expressions.
Test case: T11107
2. Error messages for illegal promotion ticks are now reported at more
precise source locations.
Test case: T17865
Internal changes:
* The definition of HsOpTy now mirrors that of OpApp:
| HsOpTy (XOpTy p) (LHsType p) (LHsType p) (LHsType p)
| OpApp (XOpApp p) (LHsExpr p) (LHsExpr p) (LHsExpr p)
This moves us one step closer to unifying HsType and HsExpr.
* Ignoring locations,
the old pattern match (HsOpTy x prom lhs op rhs)
is now written as (HsOpTy x lhs (HsTyVar x' prom op) rhs)
but we also handle (HsOpTy x lhs (HsWildCardTy x') rhs)
Constructors other than HsTyVar and HsWildCardTy never appear
in the operator position.
* The various definitions across the compiler have been updated to work
with the new representation, drawing inspiration from the term-level
pipeline where appropriate. For example,
ppr_infix_ty <=> ppr_infix_expr
get_tyop <=> get_op
lookupTypeFixityRn <=> lookupExprFixityRn
(the latter is factored out from rnExpr)
Test cases: T11107 T17865
- - - - -
5b6757d7 by mangoiv at 2026-03-27T17:23:19-04:00
ci: build i386 non-validate for deb12
This is a small fix that will unlock ghcup metadata to run, i386 debian
12 was missing as a job.
- - - - -
22ed726f by Simon Jakobi at 2026-03-28T12:38:13+01:00
Add perf test for #13960
Closes #13960.
- - - - -
226 changed files:
- .gitlab/generate-ci/gen_ci.hs
- + .gitlab/issue_templates/release_tracking.md
- .gitlab/jobs.yaml
- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- compiler/GHC.hs
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Cmm/Node.hs
- compiler/GHC/CmmToAsm/AArch64/Instr.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Config.hs
- compiler/GHC/CmmToLlvm/Mangler.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- + compiler/GHC/Core/Opt/Range.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/AddImplicitBinds.hs
- compiler/GHC/Driver/Config/CmmToLlvm.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Arrows.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Prelude/Basic.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Fixity.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Expr.hs
- compiler/GHC/StgToCmm/Utils.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Arrow.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Unit/Module/Location.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- docs/users_guide/9.16.1-notes.rst
- docs/users_guide/exts/required_type_arguments.rst
- compiler/GHC/Data/SmallArray.hs → libraries/ghc-boot/GHC/Data/SmallArray.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs
- − libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Char.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Const.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Identity.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Monoid.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Semigroup/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Traversable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
- libraries/ghc-internal/src/GHC/Internal/Functor/ZipList.hs
- libraries/ghc-internal/src/GHC/Internal/Generics.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
- libraries/ghc-internal/src/GHC/Internal/Read.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Bits.hs
- libraries/ghci/GHCi/CreateBCO.hs
- libraries/ghci/GHCi/ResolvedBCO.hs
- rts/Apply.cmm
- rts/CloneStack.c
- rts/CloneStack.h
- rts/Continuation.c
- rts/ContinuationOps.cmm
- rts/HeapStackCheck.cmm
- rts/IOManager.c
- rts/Interpreter.c
- rts/Messages.c
- rts/PrimOps.cmm
- rts/Printer.c
- rts/RaiseAsync.c
- rts/RtsFlags.c
- rts/RtsSymbols.c
- rts/STM.c
- rts/STM.h
- rts/Schedule.c
- rts/StgCRun.c
- rts/StgMiscClosures.cmm
- rts/Threads.c
- rts/Threads.h
- rts/eventlog/EventLog.c
- rts/include/rts/Bytecodes.h
- rts/include/rts/Constants.h
- rts/include/rts/PosixSource.h
- rts/include/rts/storage/TSO.h
- rts/include/stg/MiscClosures.h
- rts/win32/AsyncMIO.c
- rts/win32/AsyncMIO.h
- + testsuite/tests/bytecode/tuplestress/ByteCode.hs
- + testsuite/tests/bytecode/tuplestress/Common.hs-incl
- + testsuite/tests/bytecode/tuplestress/Obj.hs
- + testsuite/tests/bytecode/tuplestress/TupleStress.hs
- + testsuite/tests/bytecode/tuplestress/TupleStress.stdout
- + testsuite/tests/bytecode/tuplestress/all.T
- testsuite/tests/codeGen/should_run/Word2Float32.hs
- testsuite/tests/codeGen/should_run/Word2Float32.stdout
- testsuite/tests/codeGen/should_run/Word2Float64.hs
- testsuite/tests/codeGen/should_run/Word2Float64.stdout
- + testsuite/tests/concurrent/should_run/T26341.hs
- + testsuite/tests/concurrent/should_run/T26341.stdout
- + testsuite/tests/concurrent/should_run/T26341a.hs
- + testsuite/tests/concurrent/should_run/T26341a.stdout
- + testsuite/tests/concurrent/should_run/T26341b.hs
- + testsuite/tests/concurrent/should_run/T26341b.stdout
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- + testsuite/tests/ghc-api/T26910.hs
- + testsuite/tests/ghc-api/T26910.stdout
- + testsuite/tests/ghc-api/T26910_Input.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout
- testsuite/tests/ghci/scripts/T10963.stderr
- testsuite/tests/ghci/scripts/ghci064.stdout
- 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/lib/stm/T26028.hs
- + testsuite/tests/lib/stm/T26028.stdout
- + testsuite/tests/lib/stm/T26291a.hs
- + testsuite/tests/lib/stm/T26291a.stdout
- + testsuite/tests/lib/stm/T26291b.hs
- + testsuite/tests/lib/stm/T26291b.stdout
- + testsuite/tests/lib/stm/all.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- + testsuite/tests/parser/should_compile/T12002.hs
- + testsuite/tests/parser/should_compile/T12002.stderr
- testsuite/tests/parser/should_compile/all.T
- testsuite/tests/parser/should_fail/T17865.stderr
- + testsuite/tests/partial-sigs/should_compile/T11107.hs
- + testsuite/tests/partial-sigs/should_compile/T11107.stderr
- testsuite/tests/partial-sigs/should_compile/all.T
- + testsuite/tests/perf/compiler/T13820.hs
- + testsuite/tests/perf/compiler/T13960.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/rebindable/T10381.hs
- testsuite/tests/rebindable/all.T
- testsuite/tests/rts/all.T
- + testsuite/tests/rts/cloneThreadStackMigrating.hs
- + testsuite/tests/simd/should_run/StackAlignment32.hs
- + testsuite/tests/simd/should_run/StackAlignment32.stdout
- + testsuite/tests/simd/should_run/StackAlignment32_main.c
- + testsuite/tests/simd/should_run/StackAlignment64.hs
- + testsuite/tests/simd/should_run/StackAlignment64.stdout
- + testsuite/tests/simd/should_run/StackAlignment64_main.c
- testsuite/tests/simd/should_run/all.T
- + testsuite/tests/simplCore/should_compile/T19166.hs
- + testsuite/tests/simplCore/should_compile/T19166.stderr
- + testsuite/tests/simplCore/should_compile/T25718.hs
- + testsuite/tests/simplCore/should_compile/T25718.stderr
- + testsuite/tests/simplCore/should_compile/T25718a.hs
- + testsuite/tests/simplCore/should_compile/T25718a.stderr
- + testsuite/tests/simplCore/should_compile/T25718b.hs
- + testsuite/tests/simplCore/should_compile/T25718b.stderr
- + testsuite/tests/simplCore/should_compile/T25718c.hs
- + testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-32
- + testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-64
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T27071.hs
- + testsuite/tests/simplCore/should_run/T27071.stdout
- testsuite/tests/simplCore/should_run/all.T
- + testsuite/tests/typecheck/T13180/T13180.hs
- + testsuite/tests/typecheck/T13180/T13180.hs-boot
- + testsuite/tests/typecheck/T13180/T13180.stderr
- + testsuite/tests/typecheck/T13180/T13180A.hs
- + testsuite/tests/typecheck/T13180/all.T
- + testsuite/tests/typecheck/should_compile/T11141.hs
- + testsuite/tests/typecheck/should_compile/T11141.stderr
- + testsuite/tests/typecheck/should_compile/T11505Bar.hs
- + testsuite/tests/typecheck/should_compile/T11505Foo.hs
- + testsuite/tests/typecheck/should_compile/T11505Foo.hs-boot
- + testsuite/tests/typecheck/should_compile/T12046.hs
- testsuite/tests/typecheck/should_compile/T26225.hs
- testsuite/tests/typecheck/should_compile/all.T
- + testsuite/tests/typecheck/should_fail/T26823.hs
- + testsuite/tests/typecheck/should_fail/T26823.stderr
- testsuite/tests/typecheck/should_fail/all.T
- + testsuite/tests/vdq-rta/should_compile/T26967.hs
- + testsuite/tests/vdq-rta/should_compile/T26967.stderr
- + testsuite/tests/vdq-rta/should_compile/T26967_tyop.hs
- + testsuite/tests/vdq-rta/should_compile/T26967_tyop.stderr
- testsuite/tests/vdq-rta/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/deriveConstants/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.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/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/00a1f8099d7ababa5a0ca14c04bd7b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/00a1f8099d7ababa5a0ca14c04bd7b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/T27115] 38 commits: Check that shift values are valid
by Simon Jakobi (@sjakobi2) 28 Mar '26
by Simon Jakobi (@sjakobi2) 28 Mar '26
28 Mar '26
Simon Jakobi pushed to branch wip/sjakobi/T27115 at Glasgow Haskell Compiler / GHC
Commits:
aa5dfe67 by Sylvain Henry at 2026-03-26T03:48:56-04:00
Check that shift values are valid
In GHC's codebase in non-DEBUG builds we silently substitute shiftL/R
with unsafeShiftL/R for performance reasons. However we were not
checking that the shift value was valid for unsafeShiftL/R, leading to
wrong computations, but only in non-DEBUG builds.
This patch adds the necessary checks and reports an error when a wrong
shift value is passed.
- - - - -
c8a7b588 by Sylvain Henry at 2026-03-26T03:48:56-04:00
Implement basic value range analysis (#25718)
Perform basic value range analysis to try to determine at compile time
the result of the application of some comparison primops (ltWord#, etc.).
This subsumes the built-in rewrite rules used previously to check if one
of the comparison argument was a bound (e.g. (x :: Word8) <= 255 is
always True). Our analysis is more powerful and handles type
conversions: e.g. word8ToWord x <= 255 is now detected as always True too.
We also use value range analysis to filter unreachable alternatives in
case-expressions. To support this, we had to allow case-expressions for
primitive types to not have a DEFAULT alternative (as was assumed before
and checked in Core lint).
- - - - -
a5ec467e by ARATA Mizuki at 2026-03-26T03:49:49-04:00
rts: Align stack to 64-byte boundary in StgRun on x86
When LLVM spills AVX/AVX-512 vector registers to the stack, it requires
32-byte (__m256) or 64-byte (__m512) alignment. If the stack is not
sufficiently aligned, LLVM inserts a realignment prologue that reserves
%rbp as a frame pointer, conflicting with GHC's use of %rbp as an STG
callee-saved register and breaking the tail-call-based calling convention.
Previously, GHC worked around this by lying to LLVM about the stack
alignment and rewriting aligned vector loads/stores (VMOVDQA, VMOVAPS)
to unaligned ones (VMOVDQU, VMOVUPS) in the LLVM Mangler. This had two
problems:
- It did not extend to AVX-512, which requires 64-byte alignment. (#26595)
- When Haskell calls a C function that takes __m256/__m512 arguments on
the stack, the callee requires genuine alignment, which could cause a
segfault. (#26822)
This patch genuinely aligns the stack to 64 bytes in StgRun by saving
the original stack pointer before alignment and restoring it in
StgReturn. We now unconditionally advertise 64-byte stack alignment to
LLVM for all x86 targets, making rewriteAVX in the LLVM Mangler
unnecessary. STG_RUN_STACK_FRAME_SIZE is increased from 48 to 56 bytes
on non-Windows x86-64 to store the saved stack pointer.
Closes #26595 and #26822
Co-Authored-By: Claude Opus 4.5 <noreply(a)anthropic.com>
- - - - -
661da815 by Teo Camarasu at 2026-03-26T03:50:33-04:00
ghc-internal: Float Generics to near top of module graph
We remove GHC.Internal.Generics from the critical path of the
`ghc-internal` module graph. GHC.Internal.Generics used to be in the
middle of the module graph, but now it is nearer the top (built later).
This change thins out the module graph and allows us to get rid of the
ByteOrder hs-boot file.
We implement this by moving Generics instances from the module where the
datatype is defined to the GHC.Internal.Generics module. This trades off
increasing the compiled size of GHC.Internal.Generics with reducing the
dependency footprint of datatype modules.
Not all instances are moved to GHC.Internal.Generics. For instance,
`GHC.Internal.Control.Monad.Fix` keeps its instance as it is one of the
very last modules compiled in `ghc-internal` and so inverting the
relationship here would risk adding GHC.Internal.Generics back onto the
critical path.
We also don't change modules that are re-exported from the `template-haskell` or `ghc-heap`.
This is done to make it easy to eventually move `Generics` to `base`
once something like #26657 is implemented.
Resolves #26930
Metric Decrease:
T21839c
- - - - -
45428f88 by sheaf at 2026-03-26T03:51:31-04:00
Avoid infinite loop in deep subsumption
This commit ensures we only unify after we recur in the deep subsumption
code in the FunTy vs non-FunTy case of GHC.Tc.Utils.Unify.tc_sub_type_deep,
to avoid falling into an infinite loop.
See the new Wrinkle [Avoiding a loop in tc_sub_type_deep] in
Note [FunTy vs non-FunTy case in tc_sub_type_deep] in GHC.Tc.Utils.Unify.
Fixes #26823
Co-authored-by: simonpj <simon.peytonjones(a)gmail.com>
- - - - -
2823b039 by Ian Duncan at 2026-03-26T03:52:21-04:00
AArch64: fix MOVK regUsageOfInstr to mark dst as both read and written
MOVK (move with keep) modifies only a 16-bit slice of the destination
register, so the destination is both read and written. The register
allocator must know this to avoid clobbering live values. Update
regUsageOfInstr to list the destination in both src and dst sets.
No regression test: triggering the misallocation requires specific
register pressure around a MOVK sequence, which is difficult to
reliably provoke from Haskell source.
- - - - -
57b7878d by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #12002
Closes #12002.
- - - - -
c8f9df2d by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #12046
Closes #12046.
Co-authored-by: Andreas Klebinger <klebinger.andreas(a)gmx.at>
- - - - -
615d72ac by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #13180
Closes #13180.
- - - - -
423eebcf by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #11141
Closes #11141.
- - - - -
286849a4 by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #11505
Closes #11505.
- - - - -
7db149d9 by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression perf test for #13820
Closes #13820.
- - - - -
e73c4adb by Simon Jakobi at 2026-03-26T03:53:07-04:00
Add regression test for #10381
Closes #10381.
- - - - -
5ebcfb57 by Benjamin Maurer at 2026-03-26T03:54:02-04:00
Generate assembly on x86 for word2float (#22252)
We used to emit C function call for MO_UF_Conv primitive.
Now emits direct assembly instead.
Co-Authored-By: Sylvain Henry <sylvain(a)haskus.fr>
Co-Authored-By: Claude Sonnet 4.6 <noreply(a)anthropic.com>
- - - - -
5b550754 by Matthew Pickering at 2026-03-26T03:54:51-04:00
rts: forward clone-stack messages after TSO migration
MSG_CLONE_STACK assumed that the target TSO was still owned by the
capability that received the message. This is not always true: the TSO
can migrate before the inbox entry is handled.
When that happened, handleCloneStackMessage could clone a live stack from
the wrong capability and use the wrong capability for allocation and
performTryPutMVar, leading to stack sanity failures such as
checkStackFrame: weird activation record found on stack.
Fix this by passing the current capability into
handleCloneStackMessage, rechecking msg->tso->cap at handling time, and
forwarding the message if the TSO has migrated. Once ownership matches,
use the executing capability consistently for cloneStack, rts_apply, and
performTryPutMVar.
Fixes #27008
- - - - -
ef0a1bd2 by mangoiv at 2026-03-26T03:55:34-04:00
release tracking: adopt release tracking ticket from #16816
- - - - -
a7f40fd9 by mangoiv at 2026-03-26T03:55:34-04:00
release tracking: add a release tracking ticket
Brings the information in the release tracking ticket up to date with
https://gitlab.haskell.org/ghc/ghc-hq/-/blob/main/release-management.mkd
Resolves #26691
- - - - -
161d3285 by Teo Camarasu at 2026-03-26T03:56:18-04:00
Revert "Set default eventlog-flush-interval to 5s"
Flushing the eventlog forces a synchronisation of all the capabilities
and there was a worry that this might lead to a performance cost for
some highly parallel workloads.
This reverts commit 66b96e2a591d8e3d60e74af3671344dfe4061cf2.
- - - - -
36eed985 by Cheng Shao at 2026-03-26T03:57:03-04:00
ghc-boot: move GHC.Data.SmallArray to ghc-boot
This commit moves `GHC.Data.SmallArray` from the `ghc` library to
`ghc-boot`, so that it can be used by `ghci` as well:
- The `Binary` (from `ghc`) instance of `SmallArray` is moved to
`GHC.Utils.Binary`
- Util functions `replicateSmallArrayIO`, `mapSmallArrayIO`,
`mapSmallArrayM_`, `imapSmallArrayM_` , `smallArrayFromList` and
`smallArrayToList` are added
- The `Show` instance is added
- The `Binary` (from `binary`) instance is added
- - - - -
fdf828ae by Cheng Shao at 2026-03-26T03:57:03-04:00
compiler: use `Binary` instance of `BCOByteArray` for bytecode objects
This commit defines `Binary` (from `compiler`) instance of
`BCOByteArray` which serializes the underlying buffer directly, and
uses it directly in bytecode object serialization. Previously we reuse
the `Binary` (from `binary`) instance, and this change allows us to
avoid double-copying via an intermediate `ByteString` when using
`put`/`get` in `binnary`. Also see added comment for explanation.
- - - - -
3bf62d0a by Cheng Shao at 2026-03-26T03:57:03-04:00
ghci: use SmallArray directly in ResolvedBCO
This patch makes ghci use `SmallArray` directly in `ResolvedBCO` when
applicable, making the memory representation more compact and reducing
marshaling overhead. Closes #27058.
- - - - -
3d6492ce by Wen Kokke at 2026-03-26T03:57:53-04:00
Fix race condition between flushEventLog and start/endEventLogging.
This commit changes `flushEventLog` to acquire/release the `state_change` mutex to prevent interleaving with `startEventLogging` and `endEventLogging`. In the current RTS, `flushEventLog` _does not_ acquire this mutex, which may lead to eventlog corruption on the following interleaving:
- `startEventLogging` writes the new `EventLogWriter` to `event_log_writer`.
- `flushEventLog` flushes some events to `event_log_writer`.
- `startEventLogging` writes the eventlog header to `event_log_writer`.
This causes the eventlog to be written out in an unreadable state, with one or more events preceding the eventlog header.
This commit renames the old function to `flushEventLog_` and defines `flushEventLog` simply as:
```c
void flushEventLog(Capability **cap USED_IF_THREADS)
{
ACQUIRE_LOCK(&state_change_mutex);
flushEventLog_(cap);
RELEASE_LOCK(&state_change_mutex);
}
```
The old function is still needed internally within the compilation unit, where it is used in `endEventLogging` in a context where the `state_change` mutex has already been acquired. I've chosen to mark `flushEventLog_` as static and let other uses of `flushEventLog` within the RTS refer to the new version. There is one use in `hs_init_ghc` via `flushTrace`, where the new locking behaviour should be harmless, and one use in `handle_tick`, which I believe was likely vulnerable to the same race condition, so the new locking behaviour is desirable.
I have not added a test. The behaviour is highly non-deterministic and requires a program that concurrently calls `flushEventLog` and `startEventLogging`/`endEventLogging`. I encountered the issue while developing `eventlog-socket` and within that context have verified that my patch likely addresses the issue: a test that used to fail within the first dozen or so runs now has been running on repeat for several hours.
- - - - -
7b9a75f0 by Phil Hazelden at 2026-03-26T03:58:37-04:00
Fix build with werror on glibc 2.43.
We've been defining `_XOPEN_SOURCE` and `_POSIX_C_SOURCE` to the same
values as defined in glibc prior to 2.43. But in 2.43, glibc changes
them to new values, which means we get a warning when redefining them.
By `#undef`ing them first, we no longer get a warning.
Closes #27076.
- - - - -
fe6e76c5 by Tobias Haslop at 2026-03-26T03:59:30-04:00
Fix broken Haddock link to Bifunctor class in description of Functor class
- - - - -
404b71c1 by Luite Stegeman at 2026-03-27T04:40:49-04:00
Fix assert in Interpreter.c
If we skip exactly the number of words on the stack we end up on
the first word in the next chunk.
- - - - -
a85bd503 by Luite Stegeman at 2026-03-27T04:40:49-04:00
Support arbitrary size unboxed tuples in bytecode
This stores the size (number of words on the stack) of the next
expected tuple in the TSO, ctoi_spill_size field, eliminating
the need of stg_ctoi_tN frames for each size.
Note: On 32 bit platform there is still a bytecode tuple size
limit of 255 words on the stack.
Fixes #26946
- - - - -
e2209031 by Luite Stegeman at 2026-03-27T04:40:49-04:00
Add specialized frames for small tuples
Small tuples are now returned more efficiently to the interpreter.
They use one less word of stack space and don't need manipulation
of the TSO anymore.
- - - - -
b26bb2ea by VeryMilkyJoe at 2026-03-27T04:41:38-04:00
Remove backwards compatibility pattern synonym `ModLocation`
Fixes #24932
- - - - -
66e5e324 by Vladislav Zavialov at 2026-03-27T04:42:25-04:00
Extend HsExpr with the StarIsType syntax (#26587, #26967)
This patch allows kinds of the form `k -> *` and `* -> k` to occur in
expression syntax, i.e. to be used as required type arguments.
For example:
{-# LANGUAGE RequiredTypeArguments, StarIsType #-}
x1 = f (* -> * -> *)
x2 = f (forall k. k -> *)
x3 = f ((* -> *) -> Constraint)
Summary of the changes:
* Introduce the HsStar constructor of HsExpr and its extension field XStar.
It is analogous to HsStarTy in HsType.
* Refactor HsStarTy to store the unicode flag as TokStar, defined as
type TokStar = EpUniToken "*" "★" -- similar to TokForall, TokRArrow, etc.
The token is stored in the extension field and replaces the Bool field.
* Extend the `infixexp2` nonterminal to parse `*` as a direct argument of `->`.
This is more limited than the full StarIsType syntax, but has the nice
property of not conflicting with the multiplication operator `a * b`.
Test case: T26967 T26967_tyop
- - - - -
f8de456f by Sylvain Henry at 2026-03-27T04:43:22-04:00
STM: don't create a transaction in the rhs of catchRetry# (#26028)
We don't need to create a transaction for the rhs of (catchRetry#)
because contrary to the lhs we don't need to abort it on retry. Moreover
it is particularly harmful if we have code such as (#26028):
let cN = readTVar vN >> retry
tree = c1 `orElse` (c2 `orElse` (c3 `orElse` ...))
atomically tree
Because it will stack transactions for the rhss and the read-sets of all
the transactions will be iteratively merged in O(n^2) after the
execution of the most nested retry.
This is the second attempt at implementing this. The first attempt
triggered segfaults (#26291) and has been reverted.
Co-Authored-By: Claude Sonnet 4.6 <noreply(a)anthropic.com>
- - - - -
fcf092dd by Luite Stegeman at 2026-03-27T04:44:17-04:00
Windows: remove StgAsyncIOResult and fix crash/leaks
In stg_block_async{_void}, a stack slot was reserved for
an StgAsyncIOResult. This slot would be filled by the IO
manager upon completion of the async call.
However, if the blocked thread was interrupted by an async
exception, we would end up in an invalid state:
- If the blocked computation was never re-entered, the
StgAsyncIOResult would never be freed.
- If the blocked computation was re-entered, the thread would
find an unitialized stack slot for the StgAsyncIOResult,
leading to a crash reading its fields, or freeing the pointer.
We fix this by removing the StgAsyncIOResult altogether and writing
the result directly to the stack.
Fixes #26341
- - - - -
05094993 by Luite Stegeman at 2026-03-27T04:45:12-04:00
Don't refine DEFAULT alt for unary typeclasses
A non-DEFAULT data alt for a unary typeclass dictionary would
interfere with Unary Class Magic, leading to segfaults.
fixes #27071
- - - - -
4ee260cf by sheaf at 2026-03-27T04:46:06-04:00
Fix several oversights in hsExprType
This commit fixes several oversights in GHC.Hs.Syn.Type.hsExprType:
- The 'RecordCon' case was returning the type of the constructor,
instead of the constructor application. This is fixed by using
'splitFunTys'.
- The 'ExplicitTuple' case failed to take into account tuple sections,
and was also incorrectly handling 1-tuples (e.g. 'Solo') which can
be constructed using Template Haskell.
- The 'NegApp' case was returning the type of the negation operator,
again failing to apply it to the argument. Fixed by using
'funResultTy'.
- The 'HsProc' case was computing the result type of the arrow proc
block, without taking into account the argument type. Fix that by
adding a new field to 'CmdTopTc' that stores the arrow type, so that
we can construct the correct result type `arr a b` for
`proc (pat :: a) -> (cmd :: b)`.
- The 'ArithSeq' and 'NegApp' cases were failing to take into account
the result 'HsWrapper', which could e.g. silently drop casts.
This is fixed by introducing 'syntaxExpr_wrappedFunResTy' which, on
top of taking the result type, applies the result 'HsWrapper'.
These fixes are validated by the new GHC API test T26910.
Fixes #26910
- - - - -
e97232ce by Hai at 2026-03-27T04:47:04-04:00
Parser.y: avoid looking at token with QualifiedDo
This changes the behavior of 'hintQualifiedDo' so that the supplied
token is not inspected when the QualifiedDo language extension bit is
set.
- - - - -
9831385b by Vladislav Zavialov at 2026-03-27T17:22:30-04:00
Infix holes in types (#11107)
This patch introduces several improvements that follow naturally from
refactoring HsOpTy to represent the operator as an HsType, aligning it
with the approach taken by OpApp and HsExpr.
User-facing changes:
1. Infix holes (t1 `_` t2) are now permitted in types, following the
precedent set by term-level expressions.
Test case: T11107
2. Error messages for illegal promotion ticks are now reported at more
precise source locations.
Test case: T17865
Internal changes:
* The definition of HsOpTy now mirrors that of OpApp:
| HsOpTy (XOpTy p) (LHsType p) (LHsType p) (LHsType p)
| OpApp (XOpApp p) (LHsExpr p) (LHsExpr p) (LHsExpr p)
This moves us one step closer to unifying HsType and HsExpr.
* Ignoring locations,
the old pattern match (HsOpTy x prom lhs op rhs)
is now written as (HsOpTy x lhs (HsTyVar x' prom op) rhs)
but we also handle (HsOpTy x lhs (HsWildCardTy x') rhs)
Constructors other than HsTyVar and HsWildCardTy never appear
in the operator position.
* The various definitions across the compiler have been updated to work
with the new representation, drawing inspiration from the term-level
pipeline where appropriate. For example,
ppr_infix_ty <=> ppr_infix_expr
get_tyop <=> get_op
lookupTypeFixityRn <=> lookupExprFixityRn
(the latter is factored out from rnExpr)
Test cases: T11107 T17865
- - - - -
5b6757d7 by mangoiv at 2026-03-27T17:23:19-04:00
ci: build i386 non-validate for deb12
This is a small fix that will unlock ghcup metadata to run, i386 debian
12 was missing as a job.
- - - - -
3de8d08b by Simon Jakobi at 2026-03-28T12:24:57+01:00
Update diagrams of demand signature syntax
Fixes #27115.
- - - - -
308a7242 by Simon Jakobi at 2026-03-28T12:24:58+01:00
Various notation fixes regarding demand signatures
- - - - -
227 changed files:
- .gitlab/generate-ci/gen_ci.hs
- + .gitlab/issue_templates/release_tracking.md
- .gitlab/jobs.yaml
- .gitlab/rel_eng/mk-ghcup-metadata/mk_ghcup_metadata.py
- compiler/GHC.hs
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Cmm/Node.hs
- compiler/GHC/CmmToAsm/AArch64/Instr.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Config.hs
- compiler/GHC/CmmToLlvm/Mangler.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- + compiler/GHC/Core/Opt/Range.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/AddImplicitBinds.hs
- compiler/GHC/Driver/Config/CmmToLlvm.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Arrows.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Prelude/Basic.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Fixity.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm/Expr.hs
- compiler/GHC/StgToCmm/Utils.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Arrow.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Unit/Module/Location.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- docs/users_guide/9.16.1-notes.rst
- docs/users_guide/exts/required_type_arguments.rst
- docs/users_guide/using-optimisation.rst
- compiler/GHC/Data/SmallArray.hs → libraries/ghc-boot/GHC/Data/SmallArray.hs
- libraries/ghc-boot/ghc-boot.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs
- − libraries/ghc-internal/src/GHC/Internal/ByteOrder.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Char.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Foldable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Const.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Functor/Identity.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Monoid.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Semigroup/Internal.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Traversable.hs
- libraries/ghc-internal/src/GHC/Internal/Data/Version.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
- libraries/ghc-internal/src/GHC/Internal/Functor/ZipList.hs
- libraries/ghc-internal/src/GHC/Internal/Generics.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/RTS/Flags.hsc
- libraries/ghc-internal/src/GHC/Internal/Read.hs
- libraries/ghc-internal/src/GHC/Internal/Unicode/Bits.hs
- libraries/ghci/GHCi/CreateBCO.hs
- libraries/ghci/GHCi/ResolvedBCO.hs
- rts/Apply.cmm
- rts/CloneStack.c
- rts/CloneStack.h
- rts/Continuation.c
- rts/ContinuationOps.cmm
- rts/HeapStackCheck.cmm
- rts/IOManager.c
- rts/Interpreter.c
- rts/Messages.c
- rts/PrimOps.cmm
- rts/Printer.c
- rts/RaiseAsync.c
- rts/RtsFlags.c
- rts/RtsSymbols.c
- rts/STM.c
- rts/STM.h
- rts/Schedule.c
- rts/StgCRun.c
- rts/StgMiscClosures.cmm
- rts/Threads.c
- rts/Threads.h
- rts/eventlog/EventLog.c
- rts/include/rts/Bytecodes.h
- rts/include/rts/Constants.h
- rts/include/rts/PosixSource.h
- rts/include/rts/storage/TSO.h
- rts/include/stg/MiscClosures.h
- rts/win32/AsyncMIO.c
- rts/win32/AsyncMIO.h
- + testsuite/tests/bytecode/tuplestress/ByteCode.hs
- + testsuite/tests/bytecode/tuplestress/Common.hs-incl
- + testsuite/tests/bytecode/tuplestress/Obj.hs
- + testsuite/tests/bytecode/tuplestress/TupleStress.hs
- + testsuite/tests/bytecode/tuplestress/TupleStress.stdout
- + testsuite/tests/bytecode/tuplestress/all.T
- testsuite/tests/codeGen/should_run/Word2Float32.hs
- testsuite/tests/codeGen/should_run/Word2Float32.stdout
- testsuite/tests/codeGen/should_run/Word2Float64.hs
- testsuite/tests/codeGen/should_run/Word2Float64.stdout
- + testsuite/tests/concurrent/should_run/T26341.hs
- + testsuite/tests/concurrent/should_run/T26341.stdout
- + testsuite/tests/concurrent/should_run/T26341a.hs
- + testsuite/tests/concurrent/should_run/T26341a.stdout
- + testsuite/tests/concurrent/should_run/T26341b.hs
- + testsuite/tests/concurrent/should_run/T26341b.stdout
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- + testsuite/tests/ghc-api/T26910.hs
- + testsuite/tests/ghc-api/T26910.stdout
- + testsuite/tests/ghc-api/T26910_Input.hs
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/ghci/scripts/ListTuplePunsPpr.stdout
- testsuite/tests/ghci/scripts/T10963.stderr
- testsuite/tests/ghci/scripts/ghci064.stdout
- 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/lib/stm/T26028.hs
- + testsuite/tests/lib/stm/T26028.stdout
- + testsuite/tests/lib/stm/T26291a.hs
- + testsuite/tests/lib/stm/T26291a.stdout
- + testsuite/tests/lib/stm/T26291b.hs
- + testsuite/tests/lib/stm/T26291b.stdout
- + testsuite/tests/lib/stm/all.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- + testsuite/tests/parser/should_compile/T12002.hs
- + testsuite/tests/parser/should_compile/T12002.stderr
- testsuite/tests/parser/should_compile/all.T
- testsuite/tests/parser/should_fail/T17865.stderr
- + testsuite/tests/partial-sigs/should_compile/T11107.hs
- + testsuite/tests/partial-sigs/should_compile/T11107.stderr
- testsuite/tests/partial-sigs/should_compile/all.T
- + testsuite/tests/perf/compiler/T13820.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/rebindable/T10381.hs
- testsuite/tests/rebindable/all.T
- testsuite/tests/rts/all.T
- + testsuite/tests/rts/cloneThreadStackMigrating.hs
- + testsuite/tests/simd/should_run/StackAlignment32.hs
- + testsuite/tests/simd/should_run/StackAlignment32.stdout
- + testsuite/tests/simd/should_run/StackAlignment32_main.c
- + testsuite/tests/simd/should_run/StackAlignment64.hs
- + testsuite/tests/simd/should_run/StackAlignment64.stdout
- + testsuite/tests/simd/should_run/StackAlignment64_main.c
- testsuite/tests/simd/should_run/all.T
- + testsuite/tests/simplCore/should_compile/T19166.hs
- + testsuite/tests/simplCore/should_compile/T19166.stderr
- + testsuite/tests/simplCore/should_compile/T25718.hs
- + testsuite/tests/simplCore/should_compile/T25718.stderr
- + testsuite/tests/simplCore/should_compile/T25718a.hs
- + testsuite/tests/simplCore/should_compile/T25718a.stderr
- + testsuite/tests/simplCore/should_compile/T25718b.hs
- + testsuite/tests/simplCore/should_compile/T25718b.stderr
- + testsuite/tests/simplCore/should_compile/T25718c.hs
- + testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-32
- + testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-64
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T27071.hs
- + testsuite/tests/simplCore/should_run/T27071.stdout
- testsuite/tests/simplCore/should_run/all.T
- + testsuite/tests/typecheck/T13180/T13180.hs
- + testsuite/tests/typecheck/T13180/T13180.hs-boot
- + testsuite/tests/typecheck/T13180/T13180.stderr
- + testsuite/tests/typecheck/T13180/T13180A.hs
- + testsuite/tests/typecheck/T13180/all.T
- + testsuite/tests/typecheck/should_compile/T11141.hs
- + testsuite/tests/typecheck/should_compile/T11141.stderr
- + testsuite/tests/typecheck/should_compile/T11505Bar.hs
- + testsuite/tests/typecheck/should_compile/T11505Foo.hs
- + testsuite/tests/typecheck/should_compile/T11505Foo.hs-boot
- + testsuite/tests/typecheck/should_compile/T12046.hs
- testsuite/tests/typecheck/should_compile/T26225.hs
- testsuite/tests/typecheck/should_compile/all.T
- + testsuite/tests/typecheck/should_fail/T26823.hs
- + testsuite/tests/typecheck/should_fail/T26823.stderr
- testsuite/tests/typecheck/should_fail/all.T
- + testsuite/tests/vdq-rta/should_compile/T26967.hs
- + testsuite/tests/vdq-rta/should_compile/T26967.stderr
- + testsuite/tests/vdq-rta/should_compile/T26967_tyop.hs
- + testsuite/tests/vdq-rta/should_compile/T26967_tyop.stderr
- testsuite/tests/vdq-rta/should_compile/all.T
- utils/check-exact/ExactPrint.hs
- utils/deriveConstants/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.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/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Interface/RenameType.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0b9b38ed6831e8a6e216d4a8ea620c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0b9b38ed6831e8a6e216d4a8ea620c…
You're receiving this email because of your account on gitlab.haskell.org.
1
0