[Git][ghc/ghc][wip/T18927] More changes, committing so that we see a segfault
Sebastian Graf (@sgraf812)
gitlab at gitlab.haskell.org
Tue Nov 15 11:00:10 UTC 2022
Sebastian Graf pushed to branch wip/T18927 at Glasgow Haskell Compiler / GHC
Commits:
07a4f966 by Sebastian Graf at 2022-11-15T11:32:26+01:00
More changes, committing so that we see a segfault
- - - - -
5 changed files:
- compiler/GHC/Core/Opt/DmdAnal.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Data/SArr.hs
- compiler/GHC/Types/Demand.hs
Changes:
=====================================
compiler/GHC/Core/Opt/DmdAnal.hs
=====================================
@@ -40,10 +40,11 @@ import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Panic.Plain
import GHC.Data.Maybe ( isJust )
+import GHC.Data.SArr (SArr, Slice)
+import qualified GHC.Data.SArr as SArr
import GHC.Builtin.PrimOps
import GHC.Builtin.Types.Prim ( realWorldStatePrimTy )
import GHC.Types.Unique.Set
-import GHC.Exts ( IsList(..) )
import GHC.Utils.Trace
_ = pprTrace -- Tired of commenting out the import all the time
@@ -445,8 +446,8 @@ dmdAnal' env dmd (Case scrut case_bndr ty [Alt alt bndrs rhs])
| DataAlt _ <- alt
-- See Note [Demand on the scrutinee of a product case]
-- See Note [Demand on case-alternative binders]
- , (!scrut_sd, fld_dmds') <- addCaseBndrDmd case_bndr_sd (fromList fld_dmds)
- , let !bndrs' = setBndrsDemandInfo bndrs fld_dmds'
+ , (!scrut_sd, fld_dmds') <- addCaseBndrDmd case_bndr_sd (SArr.fromList fld_dmds)
+ , let !bndrs' = setBndrsDemandInfo bndrs (SArr.slice fld_dmds')
= (bndrs', scrut_sd)
| otherwise
-- __DEFAULT and literal alts. Simply add demands and discard the
@@ -560,26 +561,26 @@ dmdAnalSumAlt env dmd case_bndr (Alt con bndrs rhs)
-- See Note [Demand on case-alternative binders]
-- we can't use the scrut_sd, because it says 'Prod' and we'll use
-- topSubDmd anyway for scrutinees of sum types.
- (!_scrut_sd, dmds') = addCaseBndrDmd case_bndr_sd dmds
+ (!_scrut_sd, dmds') = addCaseBndrDmd case_bndr_sd (SArr.fromList dmds)
-- Do not put a thunk into the Alt
- !new_ids = setBndrsDemandInfo bndrs dmds'
+ !new_ids = setBndrsDemandInfo bndrs (SArr.slice dmds')
= WithDmdType alt_ty (Alt con new_ids rhs')
-- Precondition: The SubDemand is not a Call
-- See Note [Demand on the scrutinee of a product case]
-- and Note [Demand on case-alternative binders]
addCaseBndrDmd :: SubDemand -- On the case binder
- -> [Demand] -- On the fields of the constructor
- -> (SubDemand, [Demand])
+ -> SArr Demand -- On the fields of the constructor
+ -> (SubDemand, SArr Demand)
-- SubDemand on the case binder incl. field demands
-- and final demands for the components of the constructor
addCaseBndrDmd case_sd fld_dmds
| Just (_, ds) <- viewProd (length fld_dmds) scrut_sd
- = (scrut_sd, toList ds)
+ = (scrut_sd, ds)
| otherwise
= pprPanic "was a call demand" (ppr case_sd $$ ppr fld_dmds) -- See the Precondition
where
- scrut_sd = case_sd `plusSubDmd` mkProd Unboxed (fromList fld_dmds)
+ scrut_sd = case_sd `plusSubDmd` mkProd Unboxed fld_dmds
{-
Note [Analysing with absent demand]
@@ -1344,10 +1345,10 @@ conservative thing and refrain from strictifying a dfun's argument
dictionaries.
-}
-setBndrsDemandInfo :: HasCallStack => [Var] -> [Demand] -> [Var]
+setBndrsDemandInfo :: HasCallStack => [Var] -> Slice Demand -> [Var]
setBndrsDemandInfo (b:bs) ds
| isTyVar b = b : setBndrsDemandInfo bs ds
-setBndrsDemandInfo (b:bs) (d:ds) =
+setBndrsDemandInfo (b:bs) (d SArr.:<| ds) =
let !new_info = setIdDemandInfo b d
!vars = setBndrsDemandInfo bs ds
in new_info : vars
=====================================
compiler/GHC/Core/Opt/SpecConstr.hs
=====================================
@@ -57,6 +57,7 @@ import GHC.Types.Unique.FM
import GHC.Data.Maybe ( orElse, catMaybes, isJust, isNothing )
import GHC.Data.Pair
+import qualified GHC.Data.SArr as SArr
import GHC.Data.FastString
import GHC.Utils.Misc
@@ -69,7 +70,7 @@ import GHC.Utils.Trace
import GHC.Builtin.Names ( specTyConKey )
-import GHC.Exts( SpecConstrAnnotation(..), IsList(..) )
+import GHC.Exts( SpecConstrAnnotation(..) )
import GHC.Serialized ( deserializeWithData )
import Control.Monad ( zipWithM )
@@ -1836,19 +1837,19 @@ calcSpecInfo fn (CP { cp_qvars = qvars, cp_args = pats }) extra_bndrs
set_dmds (v:vs) ds@(d:ds') | isTyVar v = v : set_dmds vs ds
| otherwise = setIdDemandInfo v d : set_dmds vs ds'
- dmd_env = go emptyVarEnv fn_dmds val_pats
+ dmd_env = go emptyVarEnv (SArr.slice $ SArr.fromList fn_dmds) val_pats
- go :: DmdEnv -> [Demand] -> [CoreExpr] -> DmdEnv
+ go :: DmdEnv -> SArr.Slice Demand -> [CoreExpr] -> DmdEnv
-- We've filtered out all the type patterns already
- go env (d:ds) (pat : pats) = go (go_one env d pat) ds pats
- go env _ _ = env
+ go env (d SArr.:<| ds) (pat : pats) = go (go_one env d pat) ds pats
+ go env _ _ = env
go_one :: DmdEnv -> Demand -> CoreExpr -> DmdEnv
go_one env d (Var v) = extendVarEnv_C plusDmd env v d
go_one env (_n :* cd) e -- NB: _n does not have to be strict
| (Var _, args) <- collectArgs e
, Just (_b, ds) <- viewProd (length args) cd -- TODO: We may want to look at boxity _b, though...
- = go env (toList ds) args
+ = go env (SArr.slice ds) args
go_one env _ _ = env
=====================================
compiler/GHC/Core/Opt/WorkWrap/Utils.hs
=====================================
@@ -51,6 +51,8 @@ import GHC.Data.FastString
import GHC.Data.Maybe
import GHC.Data.OrdList
import GHC.Data.List.SetOps
+import GHC.Data.SArr (SArr)
+import qualified GHC.Data.SArr as SArr
import GHC.Builtin.Types ( tupleDataCon )
@@ -554,7 +556,7 @@ data UnboxingDecision s
-- ^ We ran out of strictness info. Leave untouched.
| DropAbsent
-- ^ The argument/field was absent. Drop it.
- | Unbox !DataConPatContext [s]
+ | Unbox !DataConPatContext !(SArr s)
-- ^ The argument is used strictly or the returned product was constructed, so
-- unbox it.
-- The 'DataConPatContext' carries the bits necessary for
@@ -581,7 +583,7 @@ wantToUnboxArg fam_envs ty (n :* sd)
, Just (Unboxed, ds) <- viewProd arity sd -- See Note [Boxity Analysis]
-- NB: No strictness or evaluatedness checks here. That is done by
-- 'finaliseBoxity'!
- = Unbox (DataConPatContext dc tc_args co) (toList ds)
+ = Unbox (DataConPatContext dc tc_args co) ds
| otherwise
= StopUnboxing
@@ -605,7 +607,7 @@ wantToUnboxResult fam_envs ty cpr
-- Deactivates CPR worker/wrapper splits on constructors with non-linear
-- arguments, for the moment, because they require unboxed tuple with variable
-- multiplicity fields.
- = Unbox (DataConPatContext dc tc_args co) arg_cprs
+ = Unbox (DataConPatContext dc tc_args co) (SArr.fromList arg_cprs)
| otherwise
= StopUnboxing
@@ -965,7 +967,7 @@ mkWWstr_one opts arg =
unbox_one_arg :: WwOpts
-> Var
- -> [Demand]
+ -> SArr Demand
-> DataConPatContext
-> UniqSM (Bool, [Var], CoreExpr -> CoreExpr, CoreExpr)
unbox_one_arg opts arg_var ds
@@ -975,7 +977,7 @@ unbox_one_arg opts arg_var ds
; let ex_name_fss = map getOccFS $ dataConExTyCoVars dc
(ex_tvs', arg_ids) =
dataConRepFSInstPat (ex_name_fss ++ repeat ww_prefix) pat_bndrs_uniqs (idMult arg_var) dc tc_args
- arg_ids' = zipWithEqual "unbox_one_arg" setIdDemandInfo arg_ids ds
+ arg_ids' = zipWithEqual "unbox_one_arg" (flip setIdDemandInfo) (toList ds) arg_ids
unbox_fn = mkUnpackCase (Var arg_var) co (idMult arg_var)
dc (ex_tvs' ++ arg_ids')
; (_, worker_args, wrap_fn, wrap_args) <- mkWWstr opts (ex_tvs' ++ arg_ids')
@@ -1284,7 +1286,7 @@ findTypeShape fam_envs ty
-- don't matter.
-- We really do encounter existentials here, see
-- Note [Which types are unboxed?] for an example.
- = TsProd (map (go rec_tc) (dubiousDataConInstArgTys con tc_args))
+ = TsProd (fromList $ map (go rec_tc) (dubiousDataConInstArgTys con tc_args))
| Just (ty', _) <- instNewTyCon_maybe tc tc_args
, Just rec_tc <- checkRecTc rec_tc tc
@@ -1449,7 +1451,7 @@ finaliseBoxity env in_inl_fun ty dmd = go NotMarkedStrict ty dmd
-- See Note [Do not unbox class dictionaries]
, in_inl_fun == NotInsideInlineableFun || not (isClassPred ty)
-- See Note [mkWWstr and unsafeCoerce]
- , ds `lengthIs` dataConRepArity dc
+ , length ds == dataConRepArity dc
, let arg_tys = dubiousDataConInstArgTys dc tc_args
-> -- pprTrace "finaliseBoxity:Unbox" (ppr ty $$ ppr dmd $$ ppr ds) $
n :* (mkProd Unboxed $! zip_go_with_marks dc arg_tys ds)
@@ -1458,9 +1460,9 @@ finaliseBoxity env in_inl_fun ty dmd = go NotMarkedStrict ty dmd
-- See Note [Unboxing evaluated arguments]
zip_go_with_marks dc arg_tys ds = case dataConWrapId_maybe dc of
- Nothing -> fromList $ strictZipWith (go NotMarkedStrict) arg_tys ds
+ Nothing -> SArr.zipWith (go NotMarkedStrict) (fromList arg_tys) ds
-- Shortcut when DataCon worker=wrapper
- Just _ -> fromList $ strictZipWith3 go (dataConRepStrictness dc) arg_tys ds
+ Just _ -> SArr.zipWith3 go (fromList $ dataConRepStrictness dc) (fromList arg_tys) ds
{-
************************************************************************
@@ -1541,7 +1543,7 @@ mkWWcpr_one :: WwOpts -> Id -> Cpr -> UniqSM CprWwResultOne
mkWWcpr_one opts res_bndr cpr
| assert (not (isTyVar res_bndr) ) True
, Unbox dcpc arg_cprs <- wantToUnboxResult (wo_fam_envs opts) (idType res_bndr) cpr
- = unbox_one_result opts res_bndr arg_cprs dcpc
+ = unbox_one_result opts res_bndr (SArr.toList arg_cprs) dcpc
| otherwise
= return (False, unitOL res_bndr, varToCoreExpr res_bndr, nop_fn)
=====================================
compiler/GHC/Data/SArr.hs
=====================================
@@ -1,4 +1,5 @@
{-# OPTIONS_GHC -Wno-unticked-promoted-constructors #-}
+{-# OPTIONS_GHC -ddump-simpl -ddump-to-file #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE RankNTypes #-}
@@ -16,20 +17,24 @@ module GHC.Data.SArr (
-- * Indexing
get, unsafeGet, (!),
-- * Construction
- take, drop, replicate,
+ fromList, toList, take, drop, replicate,
-- * Slicing
Slice(Empty,(:<|),(:|>)), slice, toSArr, takeS, dropS,
-- * Other operations
- all, map, zipWith
+ all, map, zipWith, zipWith3
) where
-import Prelude hiding (replicate, drop, take, head, init, map, all, zipWith)
+import Prelude hiding (replicate, drop, take, head, init, map, all, zipWith, zipWith3)
import qualified Prelude
import qualified Data.List as List
import qualified GHC.Exts as Exts
+import qualified GHC.Utils.Binary as Binary
import GHC.ST
-import GHC.Stack
+import GHC.Utils.Misc
+import GHC.Utils.Outputable
+
+import Data.Maybe
-- | A general-purpose array type that is strict in its elements and the
-- combinators of which enjoy list fusion.
@@ -63,7 +68,7 @@ instance Show a => Show (SArr a) where
showsPrec p arr = showParen (p >= 10) $
showString "fromList " . shows (toList arr)
-die :: String -> String -> a
+die :: HasDebugCallStack => String -> String -> a
die fun problem = error (fun ++ ": " ++ problem)
{-# NOINLINE die #-}
@@ -117,7 +122,7 @@ createSmallArrayN (Exts.I# n) x f = runST $ ST $ \s ->
{-# INLINE createSmallArrayN #-}
createSmallArray
- :: a
+ :: HasDebugCallStack => a
-> (forall s. Exts.SmallMutableArray# s a -> USTL s (Exts.SmallMutableArray# s a))
-> SArr a
createSmallArray x f = runST $ ST $ \s ->
@@ -128,6 +133,7 @@ createSmallArray x f = runST $ ST $ \s ->
!s3 = Exts.shrinkSmallMutableArray# sma' n s2
!(# s4, sa #) = Exts.unsafeFreezeSmallArray# sma' s3
-- !_ = trace ("create: " ++ show (Exts.I# n) ++ show (Exts.I# m)) ()
+ !() = foldr seq () (SArr sa)
in (# s4, SArr sa #)
{-# INLINE createSmallArray #-}
@@ -163,11 +169,11 @@ ifoldrUST f b as s = ifoldr c z as b s
z = Exts.oneShot $ \(Exts.I# i) -> Exts.oneShot $ \b s -> (# s, b, i #)
{-# INLINE ifoldrUST #-}
-dieFromList :: a
+dieFromList :: HasDebugCallStack => a
dieFromList = die "fromList" "uninitialized element"
{-# NOINLINE dieFromList #-}
-fromList :: [a] -> SArr a
+fromList :: HasDebugCallStack => [a] -> SArr a
fromList l =
createSmallArray dieFromList $ Exts.oneShot $ \sma ->
ifoldrUST (\(Exts.I# i) a sma' s -> a `seq` writeResize i a sma' s) sma l
@@ -175,11 +181,11 @@ fromList l =
-- we need [2], otherwise FB's (and their builds) will be rewritten back to
-- list producing functions and we can't fuse away the ifoldr
-dieWriteResize :: a
+dieWriteResize :: HasDebugCallStack => a
dieWriteResize = die "writeResize" "uninitialized element"
{-# NOINLINE dieWriteResize #-}
-writeResize :: Exts.Int# -> a -> Exts.SmallMutableArray# s a -> UST s (Exts.SmallMutableArray# s a)
+writeResize :: HasDebugCallStack => Exts.Int# -> a -> Exts.SmallMutableArray# s a -> UST s (Exts.SmallMutableArray# s a)
writeResize i a sma s =
let !(# s1, n #) = Exts.getSizeofSmallMutableArray# sma s -- TODO: cache this
!(# s2, sma' #)
@@ -190,19 +196,19 @@ writeResize i a sma s =
in (# s3, sma' #)
{-# NOINLINE writeResize #-}
-dieFromListN :: HasCallStack => a
+dieFromListN :: HasDebugCallStack => a
dieFromListN = die "fromListN" "uninitialized element"
{-# NOINLINE dieFromListN #-}
-fromListN :: HasCallStack => Int -> [a] -> SArr a
+fromListN :: HasDebugCallStack => Int -> [a] -> SArr a
fromListN n l =
createSmallArrayN n dieFromListN $ Exts.oneShot $ \sma s ->
case ifoldrUST (\(Exts.I# i) a _sma s -> a `seq` (# Exts.writeSmallArray# sma i a s, sma #)) sma l s of
(# s', _sma, _n #) -> (# s', sma #)
{-# INLINE [2] fromListN #-}
-toList :: SArr a -> [a]
-toList arr = Prelude.map (\i -> unsafeGet i arr) [0..length arr-1]
+toList :: HasDebugCallStack => SArr a -> [a]
+toList arr = Prelude.map (\i -> fromJust $ get i arr) [0..length arr-1]
{-# INLINE [2] toList #-}
len :: SArr a -> Int
@@ -213,14 +219,19 @@ all :: (a -> Bool) -> SArr a -> Bool
all cond = List.all cond . toList
{-# INLINE [2] all #-}
-map :: (a -> b) -> SArr a -> SArr b
-map f a = fromList $ Prelude.map f (toList a)
+map :: HasDebugCallStack => (a -> b) -> SArr a -> SArr b
+map f = fromList . Prelude.map f . toList
{-# INLINE [2] map #-}
zipWith :: (a -> b -> c) -> SArr a -> SArr b -> SArr c
zipWith f a b = fromListN (min (len a) (len b)) $ Prelude.zipWith f (toList a) (toList b)
{-# INLINE [2] zipWith #-}
+zipWith3 :: HasDebugCallStack => (a -> b -> c -> d) -> SArr a -> SArr b -> SArr c -> SArr d
+zipWith3 f a b c = fromListN (len a `min` len b `min` len c) $
+ Prelude.zipWith3 f (toList a) (toList b) (toList c)
+{-# INLINE [2] zipWith3 #-}
+
instance Eq a => Eq (SArr a) where
a1 == a2 = len a1 == len a2 && and (Prelude.map (\i -> a1 ! i == a2 ! i) [0..len a1])
@@ -238,9 +249,9 @@ fromListA l =
{-# RULES
"toList/fromList" forall xs. toList (fromList xs) = xs
-"toList/fromListN" forall n xs. toList (fromListN n xs) = xs
+"toList/fromListN" forall n xs. toList (fromListN n xs) = List.take n xs
"fromList/toList" forall arr. fromList (toList arr) = arr
-"fromListN/toList" forall n arr. fromListN n (toList arr) = arr
+-- "fromListN/toList" forall n arr. fromListN n (toList arr) = arr -- Unsafe: What if n != len arr? We need the copy here
"len/fromListN" forall n arr. len (fromListN n arr) = n
#-}
@@ -383,3 +394,10 @@ pattern a :<| rest <- (head -> Just (a, rest))
pattern (:|>) :: Slice a -> a -> Slice a
pattern rest :|> a <- (init -> Just (rest, a))
{-# COMPLETE Empty, (:|>) #-}
+
+instance Binary.Binary a => Binary.Binary (SArr a) where
+ put_ bh a = Binary.put_ bh (toList a)
+ get bh = fromList <$> Binary.get bh
+
+instance Outputable a => Outputable (SArr a) where
+ ppr = ppr . toList
=====================================
compiler/GHC/Types/Demand.hs
=====================================
@@ -93,8 +93,6 @@ import GHC.Data.Maybe ( orElse )
import GHC.Data.SArr ( SArr, Slice(..), slice )
import qualified GHC.Data.SArr as SArr
-import GHC.Exts ( IsList(..) )
-
import GHC.Core.Type ( Type )
import GHC.Core.TyCon ( isNewTyCon, isClassTyCon )
import GHC.Core.DataCon ( splitDataProductType_maybe )
@@ -737,9 +735,9 @@ mkProd :: Boxity -> SArr Demand -> SubDemand
mkProd b ds
| SArr.all (== AbsDmd) ds = Poly b C_00
| SArr.all (== BotDmd) ds = Poly b C_10
- | dmd@(n :* Poly Boxed m):<|_ <- slice ds -- don't rewrite P(L!L)
- , n == m -- don't rewrite P(1L)
- , SArr.all (== dmd) ds -- don't rewrite P(L,A)
+ | dmd@(n :* Poly Boxed m) :<| _ <- slice ds -- don't rewrite P(L!L)
+ , n == m -- don't rewrite P(1L)
+ , SArr.all (== dmd) ds -- don't rewrite P(L,A)
= Poly b n
| otherwise = Prod b ds
@@ -944,7 +942,7 @@ strictifyDictDmd :: Type -> Demand -> Demand
strictifyDictDmd ty (n :* Prod b ds)
| not (isAbs n)
, Just field_tys <- as_non_newtype_dict ty
- = C_1N :* mkProd b (SArr.zipWith strictifyDictDmd (fromList field_tys) ds)
+ = C_1N :* mkProd b (SArr.zipWith strictifyDictDmd (SArr.fromList field_tys) ds)
-- main idea: ensure it's strict
where
-- | Return a TyCon and a list of field types if the given
@@ -1954,7 +1952,7 @@ dmdTransformSig (DmdSig dmd_ty@(DmdType _ arg_ds _)) sd
-- demands into the constructor arguments.
dmdTransformDataConSig :: Arity -> DmdTransformer
dmdTransformDataConSig arity sd = case go arity sd of
- Just dmds -> DmdType emptyDmdEnv (toList dmds) topDiv
+ Just dmds -> DmdType emptyDmdEnv (SArr.toList dmds) topDiv
Nothing -> nopDmdType -- Not saturated
where
go 0 sd = snd <$> viewProd arity sd
@@ -2154,7 +2152,7 @@ kill_usage_sd _ sd = sd
data TypeShape -- See Note [Trimming a demand to a type]
-- in GHC.Core.Opt.DmdAnal
= TsFun TypeShape
- | TsProd [TypeShape]
+ | TsProd (SArr TypeShape)
| TsUnk
trimToType :: Demand -> TypeShape -> Demand
@@ -2165,8 +2163,7 @@ trimToType (n :* sd) ts
= n :* go sd ts
where
go (Prod b ds) (TsProd tss)
- | length ds == length tss' = mkProd b (SArr.zipWith trimToType ds tss') where
- tss' = fromList tss
+ | length ds == length tss = mkProd b (SArr.zipWith trimToType ds tss) where
go (Call n sd) (TsFun ts) = mkCall n (go sd ts)
go sd at Poly{} _ = sd
go _ _ = topSubDmd
@@ -2178,7 +2175,7 @@ trimBoxity BotDmd = BotDmd
trimBoxity (n :* sd) = n :* go sd
where
go (Poly _ n) = Poly Boxed n
- go (Prod _ ds) = mkProd Boxed (SArr.map trimBoxity ds)
+ go (Prod _ ds) | !_ <- foldr seq () ds = pprTrace "test" empty $ pprTrace "trimBoxity" (ppr ds $$ ppr (SArr.map trimBoxity ds)) $ Prod Boxed (SArr.map trimBoxity ds)
go (Call n sd) = mkCall n $ go sd
{-
@@ -2336,7 +2333,7 @@ instance Outputable DmdSig where
instance Outputable TypeShape where
ppr TsUnk = text "TsUnk"
ppr (TsFun ts) = text "TsFun" <> parens (ppr ts)
- ppr (TsProd tss) = parens (hsep $ punctuate comma $ map ppr tss)
+ ppr (TsProd tss) = parens (hsep $ punctuate comma $ map ppr $ SArr.toList tss)
instance Binary Card where
put_ bh C_00 = putByte bh 0
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/07a4f966a58d35fae29431448af7accc2b969a10
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/07a4f966a58d35fae29431448af7accc2b969a10
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20221115/fb30a7d7/attachment-0001.html>
More information about the ghc-commits
mailing list