[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 3 commits: EPA: Start using vocurly as basis for AnnListLayout
by Marge Bot (@marge-bot) 15 Oct '26
by Marge Bot (@marge-bot) 15 Oct '26
15 Oct '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
cf01f842 by Alan Zimmerman at 2026-10-14T20:54:03-04:00
EPA: Start using vocurly as basis for AnnListLayout
For the existing cases that populate AnnList.
This uses AnnListBraces when braces are explicitly supplied, and
AnnListLayout when vocurly is used
The change also shows up AnnList usages that can never capture layout,
these are cleared up later.
- - - - -
a6187dc3 by sheaf at 2026-10-14T20:54:07-04:00
Make exprFreeVars deep
exprFreeVars used to be a shallow free-variable finder (it didn't look
into kinds), but most callers wanted it to be deep. In particular,
'exprFreeVars' is often used to seed an 'InScopeSet', and that must
contain the /deep/ free variables.
This commit makes it deep, which allows us to get rid of calls to
'closeOverKinds' or other workarounds for shallowness in:
- 'GHC.Core.Opt.Simplify.Utils.abstractFloats'
- 'GHC.HsToCore.Binds.dsSpec_help'
- 'GHC.Core.Opt.Arity.etaBodyForJoinPoint'
- 'GHC.Core.FVs.freeVars'
- 'GHC.Core.Lint.lintCoreRule'
We also remove 'deepExprsFreeVarsDSet' and 'closeOverKindsDSet'.
Other places needed a little bit more care, in particular to properly
handle coercion variables free in kinds:
- 'GHC.Core.Opt.Specialise.specHeader' quantifies over the binder of
an unspecialised argument directly, instead of computing the free Ids
of the argument.
- 'GHC.HsToCore.dsWarnRuleShadowing' filters out 'CoVar's.
- 'GHC.Core.Opt.SpecConstr.callToPat' had some ad-hoc logic to compute
argument pattern types and a workaround with 'expandTypeSynonyms'.
That logic is removed in favour of a new 'argsToPats' function which
directly computes the argument pattern types by instantiating the
type of the head of the call pattern.
Fixes #27936
- - - - -
6786471c by Luite Stegeman at 2026-10-14T20:54:12-04:00
testsuite: Use mkWeakMVar in memo001/memo002
mkWeakPtr in the memo001/memo001 tests created weak pointers
with the MVar box as the key, which is fragile in the presence
of optimization. The fix is using mkWeakMVar, keying on the
primitive MVar# instead.
Fixes #27924 and #27396
- - - - -
21 changed files:
- + changelog.d/27936
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/Parser.y
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Types/Var/FV.hs
- libraries/base/tests/Memo1.lhs
- libraries/base/tests/Memo2.lhs
- libraries/base/tests/all.T
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- + testsuite/tests/simplCore/should_compile/T27936.hs
- testsuite/tests/simplCore/should_compile/all.T
Changes:
=====================================
changelog.d/27936
=====================================
@@ -0,0 +1,6 @@
+section: compiler
+synopsis:
+ Ensure in-scope set computations always look into kinds, avoiding
+ "needInScope" assertion failures in various places in the compiler.
+mrs: !16799
+issues: #27936
=====================================
compiler/GHC/Core/FVs.hs
=====================================
@@ -11,18 +11,17 @@ Taken quite directly from the Peyton Jones/Lester paper.
module GHC.Core.FVs (
-- * Free variables of expressions and binding groups
exprFreeVars, exprsFreeVars,
- exprFreeVarsDSet,
+ exprFreeVarsDSet, exprsFreeVarsDSet,
exprFreeVarsList, exprsFreeVarsList,
exprFreeIds, exprsFreeIds,
exprFreeIdsDSet, exprsFreeIdsDSet,
exprFreeIdsList, exprsFreeIdsList,
bindFreeVars,
- -- * Selective shallow free variables of expressions
+ -- * Selective free variables of expressions
InterestingVarFun,
exprSomeFreeVars, exprsSomeFreeVars,
exprSomeFreeVarsList, exprsSomeFreeVarsList, exprsSomeFreeVarsDSet,
- deepExprsFreeVarsDSet,
-- * Free variables of Rules, Vars and Ids
bndrTypeTyCoFVs, bndrFVs, dBndrFreeVars,
@@ -73,95 +72,118 @@ import GHC.Builtin.WiredIn.Types( unrestrictedFunTyConName )
import GHC.Builtin.WiredIn.Prim( fUNTyCon )
import GHC.Data.Maybe( orElse )
-import GHC.Utils.EndoOS
import GHC.Utils.Misc
import GHC.Utils.Panic.Plain
{-
************************************************************************
* *
- Find the shallow free variables of term
+ Free variables of terms
* *
************************************************************************
Note [Free variables of an expression]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This function simply finds the shallow free variables of an expression.
-So far as type variables are concerned, it only finds tyvars that are
- * free in type arguments,
- * free in the type of a binder,
-but not those that are free in the type of variable occurrences.
-
-(FVE1) For /types/ we have a shallow free-var finder and a deep free-var finder,
- both implemented via TyCoFolder. For /terms/ we have just one free-var
- finder (shallow).
-
- If we want the deep free vars (as in `deepExprsFreeVarsDSet`) we use
- `closeOverKinds`. There is no deep reason for this. Maybe we should
- make a folder for terms as well.
--}
+'exprFreeVars' computes the /deep/ free variables of an expression, in the
+sense of Note [Shallow and deep free variables] in GHC.Core.TyCo.FVs:
+
+(FVE1) An occurrence of a variable `v` contributes `v` together with the deep
+ free variables of v's type (and, for an Id, of its multiplicity).
+The selective variants, e.g. 'exprSomeFreeVars', are also deep.
+They only collect interesting free variables, and entirely skip looking into
+the kind of non-interesting free variables.
+
+The type of a variable is traversed only when the variable is first collected,
+so each free variable's type is visited at most once per call; see
+Note [Computing deep free variables] in GHC.Core.TyCo.FVs.
+-}
-- | Find all locally-defined free Ids or type variables in an expression
-- returning a non-deterministic set.
+--
+-- The result is deep; see Note [Free variables of an expression].
exprFreeVars :: CoreExpr -> VarSet
exprFreeVars = dVarSetToVarSet . exprFreeVarsDSet
-- | Find all locally-defined free Ids or type variables in an expression
-- returning a deterministic set.
+--
+-- The result is deep; see Note [Free variables of an expression].
exprFreeVarsDSet :: CoreExpr -> DVarSet
exprFreeVarsDSet = runFVSelective isLocalVar . exprFVs
--- | Find all locally-defined free Ids or type variables in several expressions
+-- | Find all locally-defined free Ids or type variables in several expressions,
-- returning a non-deterministic set.
+--
+-- The result is deep; see Note [Free variables of an expression].
exprsFreeVars :: [CoreExpr] -> VarSet
exprsFreeVars = dVarSetToVarSet . exprsFreeVarsDSet
--- | Find all locally-defined free Ids or type variables in several expressions
+-- | Find all locally-defined free Ids or type variables in several expressions,
-- returning a deterministically ordered list.
+--
+-- The result is deep; see Note [Free variables of an expression].
exprsFreeVarsList :: [CoreExpr] -> [Var]
exprsFreeVarsList = runFVSelectiveList isLocalVar . exprsFVs
+-- | Find all locally-defined free Ids or type variables in several expressions,
+-- returning a deterministic set.
+--
+-- The result is deep; see Note [Free variables of an expression].
exprsFreeVarsDSet :: [CoreExpr] -> DVarSet
exprsFreeVarsDSet = runFVSelective isLocalVar . exprsFVs
-deepExprsFreeVarsDSet :: [CoreExpr] -> DVarSet
--- See (FVE1) in Note [Free variables of an expression]
-deepExprsFreeVarsDSet = closeOverKindsDSet . exprsFreeVarsDSet
-
-- | Find all locally-defined free Ids or type variables in an expression
-- returning a deterministically ordered list.
+--
+-- The result is deep; see Note [Free variables of an expression].
exprFreeVarsList :: CoreExpr -> [Var]
exprFreeVarsList = dVarSetElems . exprFreeVarsDSet
--- | Find all locally-defined free Ids in an expression
-exprFreeIds :: CoreExpr -> IdSet -- Find all locally-defined free Ids
+-- | Find all locally-defined free Ids in an expression.
+--
+-- The result is deep; see Note [Free variables of an expression].
+exprFreeIds :: CoreExpr -> IdSet
exprFreeIds = dVarSetToVarSet . exprFreeIdsDSet
-exprsFreeIds :: [CoreExpr] -> IdSet -- Find all locally-defined free Ids
+-- | Find all locally-defined free Ids in several expressions.
+--
+-- The result is deep; see Note [Free variables of an expression].
+exprsFreeIds :: [CoreExpr] -> IdSet
exprsFreeIds = dVarSetToVarSet . exprsFreeIdsDSet
-- | Find all locally-defined free Ids in an expression
-- returning a deterministic set.
-exprFreeIdsDSet :: CoreExpr -> DIdSet -- Find all locally-defined free Ids
+--
+-- The result is deep; see Note [Free variables of an expression].
+exprFreeIdsDSet :: CoreExpr -> DIdSet
exprFreeIdsDSet = runFVSelective isLocalId . exprFVs
-- | Find all locally-defined free Ids in several expressions
-- returning a deterministic set.
-exprsFreeIdsDSet :: [CoreExpr] -> DIdSet -- Find all locally-defined free Ids
+--
+-- The result is deep; see Note [Free variables of an expression].
+exprsFreeIdsDSet :: [CoreExpr] -> DIdSet
exprsFreeIdsDSet = runFVSelective isLocalId . exprsFVs
-- | Find all locally-defined free Ids in an expression
-- returning a deterministically ordered list.
-exprFreeIdsList :: CoreExpr -> [Id] -- Find all locally-defined free Ids
+--
+-- The result is deep; see Note [Free variables of an expression].
+exprFreeIdsList :: CoreExpr -> [Id]
exprFreeIdsList = dVarSetElems . exprFreeIdsDSet
-- | Find all locally-defined free Ids in several expressions
-- returning a deterministically ordered list.
-exprsFreeIdsList :: [CoreExpr] -> [Id] -- Find all locally-defined free Ids
+--
+-- The result is deep; see Note [Free variables of an expression].
+exprsFreeIdsList :: [CoreExpr] -> [Id]
exprsFreeIdsList = dVarSetElems . exprsFreeIdsDSet
--- | Find all locally defined free Ids in a binding group
+-- | Find all locally-defined free Ids or type variables in a binding group.
+--
+-- The result is deep; see Note [Free variables of an expression].
bindFreeVars :: CoreBind -> VarSet
bindFreeVars = runFVSelectiveSet isLocalVar . bind_fvs
@@ -171,6 +193,8 @@ bind_fvs (Rec prs) = addBndrsSelectiveFV (map fst prs) $
mapUnionFV rhs_fvs prs
-- | Finds free variables in an expression selected by a predicate
+--
+-- See Note [Free variables of an expression].
exprSomeFreeVars :: InterestingVarFun -- ^ Says which 'Var's are interesting
-> CoreExpr
-> VarSet
@@ -221,30 +245,25 @@ addCoreBndrsFV :: [CoreBndr] -> SelectiveDFV -> SelectiveDFV
addCoreBndrsFV bndrs fv = foldr addCoreBndrFV fv bndrs
unitFV :: Var -> SelectiveDFV
--- Deals with an occurrence
--- Shallow: does not look at the kind
-unitFV v = MkFV (\env -> EndoOS (do_it env))
- where
- do_it (bvs, is_interesting) acc
- | v `elemVarSet` bvs = acc -- First exclude the bound vars
- | not (is_interesting v) = acc -- The "selective" bit
- | v `elemDVarSet` acc = acc
- | otherwise = acc `extendDVarSet` v
+-- Deals with an occurrence: the variable and, if it is newly collected,
+-- the free variables of its type and multiplicity.
+-- See (FVE1) in Note [Free variables of an expression]
+unitFV = deepSelUnitFV bndrTypeTyCoFVs
exprsFVs :: [CoreExpr] -> SelectiveDFV
exprsFVs = mapUnionFV exprFVs
exprFVs :: CoreExpr -> SelectiveDFV
-exprFVs (Type ty) = shallowSelTypeFV ty
-exprFVs (Coercion co) = shallowSelCoFV co
+exprFVs (Type ty) = deepSelTypeFV ty
+exprFVs (Coercion co) = deepSelCoFV co
exprFVs (Var var) = unitFV var
exprFVs (Lit _) = mempty
exprFVs (Tick t expr) = tickish_fvs t `mappend` exprFVs expr
exprFVs (App fun arg) = exprFVs fun `mappend` exprFVs arg
exprFVs (Lam bndr body) = addCoreBndrFV bndr (exprFVs body)
-exprFVs (Cast expr co) = exprFVs expr `mappend` shallowSelCoFV co
+exprFVs (Cast expr co) = exprFVs expr `mappend` deepSelCoFV co
exprFVs (Case scrut bndr ty alts)
- = exprFVs scrut `mappend` shallowSelTypeFV ty `mappend`
+ = exprFVs scrut `mappend` deepSelTypeFV ty `mappend`
addCoreBndrFV bndr (mapUnionFV alt_fvs alts)
where
alt_fvs (Alt _ bndrs rhs) = addCoreBndrsFV bndrs (exprFVs rhs)
@@ -267,13 +286,13 @@ tickish_fvs _ = mempty
---------
bndrTypeTyCoFVs :: Var -> SelectiveDFV
--- Find the free variables of a binder.
+-- Find the (deep) free variables of the type of a variable.
-- In the case of ids, don't forget the multiplicity field!
bndrTypeTyCoFVs var
- = shallowSelTypeFV (varType var) `mappend` mult_fvs
+ = deepSelTypeFV (varType var) `mappend` mult_fvs
where
mult_fvs = case varMultMaybe var of
- Just mult -> shallowSelTypeFV mult
+ Just mult -> deepSelTypeFV mult
Nothing -> mempty
dBndrTypeTyCoVars :: Var -> DTyCoVarSet
@@ -286,11 +305,10 @@ bndrFreeVars id = assert (isId id) $
dBndrFreeVars id
dBndrFreeVars :: Id -> DVarSet
--- Shallow free vars
dBndrFreeVars id = runFVSelective isLocalVar $ bndrFVs id
bndrFVs :: Id -> SelectiveDFV
--- Shallow free vars of types, rules, and inlining
+-- Free vars of types, rules, and inlining
bndrFVs id = assert (isId id) $
bndrTypeTyCoFVs id `mappend`
bndrRuleAndUnfoldingFVs id
@@ -593,7 +611,8 @@ Note [The FVAnn invariant]
Invariant: a FVAnn, say S, is closed:
That is: if v is in S,
then freevars( v's type/kind ) is also in S
-So FVAnn computes /deep/ free variables
+So FVAnn computes /deep/ free variables, just like `exprFreeVars` does;
+see Note [Free variables of an expression].
-}
type FVAnn = DVarSet -- See Note [The FVAnn invariant]
@@ -690,22 +709,15 @@ freeVars = go
where
go :: CoreExpr -> CoreExprWithFVs
go (Var v)
- | isLocalVar v = (aFreeVar v `unionDVarSet` ty_fvs `unionDVarSet` mult_vars, AnnVar v)
- | otherwise = (emptyDVarSet, AnnVar v)
- where
- mult_vars = tyCoVarsOfTypeDSet (idMult v)
- ty_fvs = dBndrTypeTyCoVars v
- -- See Note [The FVAnn invariant]
+ | isLocalVar v = (aFreeVar v `unionDVarSet` dBndrTypeTyCoVars v, AnnVar v)
+ -- See Note [The FVAnn invariant]
+ | otherwise = (emptyDVarSet, AnnVar v)
go (Lit lit) = (emptyDVarSet, AnnLit lit)
go (Lam b body)
- = ( b_fvs `unionDVarSet` (b `delBinderFV` body_fvs)
- , AnnLam b body' )
+ = ( b `delBinderFV` body_fvs, AnnLam b body' )
where
body'@(body_fvs, _) = go body
- b_ty = idType b
- b_fvs = tyCoVarsOfTypeDSet b_ty
- -- See Note [The FVAnn invariant]
go (App fun arg)
= ( freeVarsOf fun' `unionDVarSet` freeVarsOf arg'
@@ -750,8 +762,7 @@ freeVars = go
, AnnTick tickish expr2 )
where
expr2 = go expr
- tickishFVs (Breakpoint _ _ ids) = mkDVarSet ids
- tickishFVs _ = emptyDVarSet
+ tickishFVs = runFVSelective isLocalVar . tickish_fvs
go (Type ty) = (tyCoVarsOfTypeDSet ty, AnnType ty)
go (Coercion co) = (tyCoVarsOfCoDSet co, AnnCoercion co)
=====================================
compiler/GHC/Core/Lint.hs
=====================================
@@ -2216,7 +2216,8 @@ lintCoreRule fun fun_ty rule@(Rule { ru_name = name, ru_bndrs = bndrs
where
rule_doc = text "Rule" <+> doubleQuotes (ftext name) <> colon
- lhs_fvs = deepExprsFreeVarsDSet args -- Matching binds deeply
+ lhs_fvs = exprsFreeVarsDSet args -- Rule matching binds deeply, so compare
+ -- against the deep free vars
rhs_fvs = exprFreeVarsDSet rhs
is_bad_bndr :: Var -> Bool
=====================================
compiler/GHC/Core/Opt/Arity.hs
=====================================
@@ -3230,15 +3230,12 @@ etaBodyForJoinPoint need_args body
ppr body $$ ppr (exprType body)
body_ty = exprType body
- in_scope = mkInScopeSet (exprFreeVars body `unionVarSet` tyCoVarsOfType body_ty)
- -- in_scope is a bit tricky.
- -- - We are wrapping `body` in some value lambdas, so must not shadow
- -- any free vars of `body`
- -- - We are wrapping `body` in some type lambdas, so must not shadow any
- -- tyvars in body_ty. Example: body is just a variable
- -- (g :: forall (a::k). T k a -> Int)
- -- We must not shadown that `k` when adding the /\a. So treat the free vars
- -- of body_ty as in-scope. Showed up in #23026.
+ in_scope = mkInScopeSet (exprFreeVars body)
+ -- We are wrapping `body` in lambdas, so the in-scope set must contain the
+ -- /deep/ free vars of `body` (exprFreeVars returns deep free vars).
+ -- Why? See Note [No type-shadowing in Core]: if body is just a variable
+ -- (g :: forall (a::k). T k a -> Int)
+ -- we must not shadow that `k` when adding the /\a (#23026).
--------------
freshEtaId :: Int -> Subst -> Scaled Type -> (Subst, Id)
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -2360,13 +2360,14 @@ new binding is abstracted. Several points worth noting
poly_t = /\ a b -> (e1, e2)
poly_x = /\ a -> fst (poly_t a *b*)
-(AB2) We must do closeOverKinds. Example (#10934):
+(AB2) We must abstract over kind variables too. Example (#10934):
f = /\k (f:k->*) (a:k). let t = AccFailure @ (f a) in ...
Here we want to float 't', but we must remember to abstract over
'k' as well, even though it is not explicitly mentioned in the RHS,
otherwise we get
t = /\ (f:k->*) (a:k). AccFailure @ (f a)
- which is obviously bogus.
+ which is obviously bogus. `exprSomeFreeVars isTyVar` is deep,
+ so the kind variables are picked up with the rest.
(AB3) We get the variables to abstract over by filtering down the
the main_tvs for the original function, picking only ones
@@ -2449,7 +2450,7 @@ abstractFloats uf_opts top_lvl main_tvs floats body
rhs' = GHC.Core.Subst.substExpr subst rhs
-- tvs_here: see Note [Which type variables to abstract over]
- tvs_here = choose_tvs (exprSomeFreeVars isTyVar rhs')
+ tvs_here = choose_tvs (exprSomeFreeVars isTyVar rhs') -- (AB2)
abstract subst (CyclicSCC trpls)
= do { (poly_ids, poly_apps) <- mapAndUnzipM (mk_poly1 tvs_here) ids
@@ -2478,14 +2479,12 @@ abstractFloats uf_opts top_lvl main_tvs floats body
-- because it has a non-CoVar precondition
| Just poly_app <- GHC.Core.Subst.lookupIdSubst_maybe subst var
= -- 'var' is like 'x' in (AB4)
- exprSomeFreeVars isTyVar poly_app `unionVarSet` free_tvs
+ exprSomeFreeVars isTyVar poly_app `unionVarSet` free_tvs -- (AB2)
| otherwise
= free_tvs
choose_tvs free_tvs
- = filter (`elemVarSet` all_free_tvs) main_tvs -- (AB3)
- where
- all_free_tvs = closeOverKinds free_tvs -- (AB2)
+ = filter (`elemVarSet` free_tvs) main_tvs -- (AB3)
mk_poly1 :: [TyVar] -> Id -> SimplM (Id, CoreExpr)
mk_poly1 tvs_here var
=====================================
compiler/GHC/Core/Opt/SpecConstr.hs
=====================================
@@ -60,6 +60,7 @@ import GHC.Types.Unique( hasKey )
import GHC.Data.Maybe ( fromMaybe, orElse, catMaybes, isJust, isNothing )
import GHC.Data.FastString
+import GHC.Data.Pair
import GHC.Utils.Misc
import GHC.Utils.Outputable
@@ -2317,17 +2318,18 @@ they are constructor applications.
Note [Free type variables of the qvar types]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In a call (f @a x True), that we want to specialise, what variables should
-we quantify over. Clearly over 'a' and 'x', but what about any type variables
-free in x's type? In fact we don't need to worry about them because (f @a)
-can only be a well-typed application if its type is compatible with x, so any
-variables free in x's type must be free in (f @a), and hence either be gathered
-via 'a' itself, or be in scope at f's defn. Hence we just take
- (exprsFreeVars pats).
-
-BUT phantom type synonyms can mess this reasoning up,
- eg x::T b with type T b = Int
-So we apply expandTypeSynonyms to the bound Ids.
-See # 5458. Yuk.
+we quantify over? Clearly over 'a' and 'x', but what about any type variables
+free in x's type? In fact we don't need to worry about them, because
+argsToPats gives 'x' the type of the corresponding argument of f, instantiated
+at the type arguments of the call pattern (and similarly for the fields of a
+data constructor in the pattern). So any variables free in x's type are free
+in (f @a), and hence either gathered via 'a' itself, or in scope at f's defn.
+Hence we just take (exprsFreeVars pats).
+
+We do not use the type of the actual argument: it is not necessarily
+syntactically equal to the type of f's argument, and so may mention other
+variables, e.g. with a phantom type synonym (#5458)
+ x::T b with type T b = Int
Note [SpecConstr call patterns]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2337,7 +2339,7 @@ Wrinkles:
* The list of argument patterns, cp_args, is no longer than the
visible lambdas of the binding, ri_arg_occs. This is done via
- the zipWithM in callToPat.
+ argsToPats in callToPat.
* The list of argument patterns can certainly be shorter than the
lambdas in the function definition (under-saturated). For example
@@ -2602,8 +2604,9 @@ callToPat :: ScEnv -> [ArgOcc] -> Call -> UniqSM (Maybe CallPat)
callToPat env bndr_occs call@(Call fn args con_env)
= do { let in_scope = substInScopeSet (sc_subst env)
- ; arg_triples <- zipWith3M (argToPat env in_scope con_env) args bndr_occs (map (const NotMarkedStrict) args)
- -- This zip trims the args to be no longer than
+ ; arg_triples <- argsToPats env in_scope con_env (idType fn) args bndr_occs
+ (repeat NotMarkedStrict)
+ -- This trims the args to be no longer than
-- the lambdas in the function definition (bndr_occs)
-- Drop boring patterns from the end
@@ -2631,14 +2634,11 @@ callToPat env bndr_occs call@(Call fn args con_env)
-- See Note [Shadowing in SpecConstr] at the top
(qktvs, qids) = partition isTyVar qvars
- qvars' = scopedSort qktvs ++ map sanitise qids
+ qvars' = scopedSort qktvs ++ qids
-- Order into kind variables, type variables, term variables
-- The kind of a type variable may mention a kind variable
-- and the type of a term variable may mention a type variable
- sanitise id = updateIdTypeAndMult expandTypeSynonyms id
- -- See Note [Free type variables of the qvar types]
-
-- Check for bad coercion variables: see Note [SpecConstr and casts]
; let bad_covars = filter isCoVar qids
; warnPprTrace (not (null bad_covars))
@@ -2657,18 +2657,49 @@ callToPat env bndr_occs call@(Call fn args con_env)
; return (Just cp_res) }
else return Nothing }
- -- argToPat takes an actual argument, and returns an abstracted
- -- version, consisting of just the "constructor skeleton" of the
- -- argument, with non-constructor sub-expression replaced by new
- -- placeholder variables. For example:
- -- C a (D (f x) (g y)) ==> C p1 (D p2 p3)
+-- | Turn the arguments of an application into patterns using 'argToPat'.
+--
+-- See Note [Free type variables of the qvar types].
+argsToPats :: ScEnv
+ -> InScopeSet -- ^ what's in scope at the function definition site
+ -> ValueEnv -- ^ 'ValueEnv' at the call site
+ -> Type -- ^ type of the head (function or data constructor)
+ -> [CoreArg] -- ^ arguments of the head
+ -> [ArgOcc] -- ^ occurrence info, one per argument; the result is trimmed to this length
+ -> [StrictnessMark] -- ^ strictness info, one per value argument
+ -> UniqSM [(Bool, CoreArg, [Id])]
+argsToPats env in_scope val_env = go
+ where
+ go _ [] _ _ = return []
+ go _ _ [] _ = return []
+ go fun_ty (arg : args) (occ : occs) strs
+ = do { (pat, strs') <- case arg of
+ Type {} -> do { pat <- argToPat env in_scope val_env arg_ty arg occ NotMarkedStrict
+ ; return (pat, strs) }
+ _ | str : strs' <- strs
+ -> do { pat <- argToPat env in_scope val_env arg_ty arg occ str
+ ; return (pat, strs') }
+ | otherwise
+ -> pprPanic "argsToPats: more value arguments than strictness marks"
+ (ppr fun_ty $$ ppr (arg : args))
+ ; pats <- go (applyTypeToArgs fun_ty [sndOf3 pat]) args occs strs'
+ ; return (pat : pats) }
+ where
+ arg_ty = piTyBinderType (fst (splitPiTy fun_ty))
+-- | 'argToPat' takes an actual argument, and returns an abstracted
+-- version, consisting of just the "constructor skeleton" of the
+-- argument, with non-constructor sub-expression replaced by new
+-- placeholder variables. For example:
+--
+-- > C a (D (f x) (g y)) ==> C p1 (D p2 p3)
argToPat :: ScEnv
- -> InScopeSet -- What's in scope at the fn defn site
- -> ValueEnv -- ValueEnv at the call site
- -> CoreArg -- A call arg (or component thereof)
- -> ArgOcc
- -> StrictnessMark -- Tells us if this argument is a strict field of a data constructor
+ -> InScopeSet -- ^ what's in scope at the function definition site
+ -> ValueEnv -- ^ 'ValueEnv' at the call site
+ -> Type -- ^ type for this argument
+ -> CoreArg -- ^ A call arg (or component thereof)
+ -> ArgOcc -- ^ occurrence info for the argument
+ -> StrictnessMark -- ^ Tells us if this argument is a strict field of a data constructor
-- See Note [SpecConstr and strict fields]
-> UniqSM (Bool, CoreArg, [Id])
@@ -2682,25 +2713,26 @@ argToPat :: ScEnv
-- lvl7 --> (True, lvl7) if lvl7 is bound
-- somewhere further out
-argToPat env in_scope val_env arg arg_occ arg_str
+argToPat env in_scope val_env pat_ty arg arg_occ arg_str
= do
-- pprTraceM "argToPatIn" (ppr arg)
- !res <- argToPat1 env in_scope val_env arg arg_occ arg_str
+ !res <- argToPat1 env in_scope val_env pat_ty arg arg_occ arg_str
-- pprTraceM "argToPatOut" (ppr res)
return res
argToPat1 :: ScEnv
-> InScopeSet
-> ValueEnv
+ -> Type
-> Expr CoreBndr
-> ArgOcc
-> StrictnessMark
-> UniqSM (Bool, Expr CoreBndr, [Id])
-argToPat1 _env _in_scope _val_env arg@(Type {}) _arg_occ _arg_str
+argToPat1 _env _in_scope _val_env _pat_ty arg@(Type {}) _arg_occ _arg_str
= return (False, arg, [])
-argToPat1 env in_scope val_env (Tick _ arg) arg_occ arg_str
- = argToPat env in_scope val_env arg arg_occ arg_str
+argToPat1 env in_scope val_env pat_ty (Tick _ arg) arg_occ arg_str
+ = argToPat env in_scope val_env pat_ty arg arg_occ arg_str
-- Note [Tick annotations in call patterns]
-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-- Ignore Notes. In particular, we want to ignore any InlineMe notes
@@ -2708,8 +2740,8 @@ argToPat1 env in_scope val_env (Tick _ arg) arg_occ arg_str
-- ride roughshod over them all for now.
--- See Note [Tick annotations in RULE matching] in GHC.Core.Rules
-argToPat1 env in_scope val_env (Let _ arg) arg_occ arg_str
- = argToPat env in_scope val_env arg arg_occ arg_str
+argToPat1 env in_scope val_env pat_ty (Let _ arg) arg_occ arg_str
+ = argToPat env in_scope val_env pat_ty arg arg_occ arg_str
-- See Note [Matching lets] in "GHC.Core.Rules"
-- Look through let expressions
-- e.g. f (let v = rhs in (v,w))
@@ -2717,35 +2749,34 @@ argToPat1 env in_scope val_env (Let _ arg) arg_occ arg_str
-- because the rule-matcher will look through the let.
-- Casts: see Note [SpecConstr and casts]
-argToPat1 env in_scope val_env (Cast arg co) arg_occ arg_str
+argToPat1 env in_scope val_env pat_ty (Cast arg co) arg_occ arg_str
| not (ignoreType env ty2)
- = do { (interesting, arg', strict_args) <- argToPat env in_scope val_env arg arg_occ arg_str
+ = do { (interesting, arg', strict_args) <- argToPat env in_scope val_env ty1 arg arg_occ arg_str
; if not interesting then
- wildCardPat ty2 arg_str
+ wildCardPat pat_ty arg_str
else
return (interesting, Cast arg' co, strict_args) }
where
- ty2 = coercionRKind co
+ Pair ty1 ty2 = coercionKind co
-- Check for a constructor application
-- NB: this *precedes* the Var case, so that we catch nullary constrs
-argToPat1 env in_scope val_env arg arg_occ _arg_str
+argToPat1 env in_scope val_env _pat_ty arg arg_occ _arg_str
| Just (ConVal _wf (DataAlt dc) args) <- isValue val_env arg
-- Ignore `_wf` here; see Note [ConVal work-free-ness] (2)
, not (ignoreDataCon env dc) -- See Note [NoSpecConstr]
, Just arg_occs <- mb_scrut dc
= do { let (ty_args, rest_args) = splitAtList (dataConUnivTyVars dc) args
- con_str, matched_str :: [StrictnessMark]
+ con_str :: [StrictnessMark]
-- con_str corresponds 1-1 with the /value/ arguments
- -- matched_str corresponds 1-1 with /all/ arguments
con_str = dataConRepStrictness dc
- matched_str = match_vals con_str rest_args
+ con_ty = applyTypeToArgs (dataConRepType dc) ty_args
-- ; pprTraceM "bangs" (ppr (length rest_args == length con_str) $$
-- ppr dc $$
-- ppr con_str $$
-- ppr rest_args $$
-- ppr (map isTypeArg rest_args))
- ; prs <- zipWith3M (argToPat env in_scope val_env) rest_args arg_occs matched_str
+ ; prs <- argsToPats env in_scope val_env con_ty rest_args arg_occs con_str
; let args' = map sndOf3 prs :: [CoreArg]
; assertPpr (length con_str == length (filter isRuntimeArg rest_args))
( ppr con_str $$ ppr rest_args $$
@@ -2760,17 +2791,6 @@ argToPat1 env in_scope val_env arg arg_occ _arg_str
-> Just (repeat UnkOcc)
| otherwise
-> Nothing
- match_vals bangs (arg:args)
- | isTypeArg arg
- = NotMarkedStrict : match_vals bangs args
- | (b:bs) <- bangs
- = b : match_vals bs args
- match_vals [] [] = []
- match_vals as bs =
- pprPanic "spec-constr:argToPat - Bangs don't match value arguments"
- (text "arg:" <> ppr arg $$
- text "remaining args:" <> ppr as $$
- text "remaining bangs:" <> ppr bs)
-- Check if the argument is a variable that
-- (a) is used in an interesting way in the function body
@@ -2779,7 +2799,7 @@ argToPat1 env in_scope val_env arg arg_occ _arg_str
-- business of absence analysis, not SpecConstr.)
-- (b) we know what its value is
-- In that case it counts as "interesting"
-argToPat1 env in_scope val_env (Var v) arg_occ arg_str
+argToPat1 env in_scope val_env _pat_ty (Var v) arg_occ arg_str
| sc_force env || specialisableArgOcc arg_occ -- (a)
-- See Note [Forcing specialisation], point (FS3)
, is_value -- (b)
@@ -2836,8 +2856,8 @@ argToPat in_scope val_env arg arg_occ
-- The default case: make a wild-card
-- We use this for coercions too
-argToPat1 _env _in_scope _val_env arg _arg_occ arg_str
- = wildCardPat (exprType arg) arg_str
+argToPat1 _env _in_scope _val_env pat_ty _arg _arg_occ arg_str
+ = wildCardPat pat_ty arg_str
-- | wildCardPats are always boring
wildCardPat :: Type -> StrictnessMark -> UniqSM (Bool, CoreArg, [Id])
=====================================
compiler/GHC/Core/Opt/Specialise.hs
=====================================
@@ -2111,7 +2111,7 @@ to push the cast back inside. It would be terrible if the cast
defeated specialisation! Hence the use of collectBindersPushingCo.
Note [Evidence foralls]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~
Suppose (#12212) that we are specialising
f :: forall a b. (Num a, F a ~# F b) => blah
with a=b=Int. Then the RULE will be something like
@@ -2120,18 +2120,13 @@ with a=b=Int. Then the RULE will be something like
where that `g` is really (Coercion (CoVar g)), since `g` is a
coercion variable and can't appear as (Var g).
-But both varToCoreExpr (when constructing the LHS args), and the
-simplifier (when simplifying the LHS args), will transform to
+When simplifying the LHS args, the simplifier may replace g with Refl:
RULE forall (d:Num Int) (g :: F Int ~ F Int).
f Int Int d <F Int> = f_spec
-by replacing g with Refl. So now 'g' is unbound, which results in a later
-crash. So we use Refl right off the bat, and do not forall-quantify 'g':
- * varToCoreExpr generates a (Coercion Refl)
- * exprsFreeIdsList returns the Ids bound by the args,
- which won't include g
-
-You might wonder if this will match as often, but the simplifier replaces
-complicated Refl coercions with Refl pretty aggressively.
+So now 'g' is unbound on the LHS. That is OK: since g's type is
+reflexive, the rule matcher instantiates it to Refl when the rule fires;
+see Note [Unbound RULE binders] in GHC.Core.Rules. So specHeader simply
+forall-quantifies 'g' like any other unspecialised binder.
Note [Orphans and auto-generated rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -2483,13 +2478,13 @@ instance Outputable SpecArg where
ppr UnspecArg = text "UnspecArg"
specArgsFVs :: InterestingVarFun -> [SpecArg] -> VarSet
--- Find the shallow deep free vars of the SpecArgs that are not already in scope
+-- Find the (deep) free vars of the SpecArgs
specArgsFVs interesting args
= runFVSelectiveSet interesting $
mapUnionFV get args
where
get :: SpecArg -> SelectiveDFV
- get (SpecType ty) = shallowSelTypeFV ty
+ get (SpecType ty) = deepSelTypeFV ty
get (SpecDict dx) = exprFVs dx
get UnspecType = mempty
get UnspecArg = mempty
@@ -2652,15 +2647,12 @@ specHeader subst (bndr:bndrs) (UnspecArg : args)
<- specHeader subst1 bndrs args
; let dummy_arg = varToCoreExpr bndr'
- -- dummy_arg is usually just (Var bndr),
- -- but if bndr :: t1 ~# t2, it'll be (Coercion (CoVar bndr))
- -- or even Coercion Refl (if t1=t2)
- -- See Note [Evidence foralls]
- bndrs = exprFreeIdsList dummy_arg
+ -- dummy_arg is (Var bndr'), or (Coercion (CoVarCo bndr'))
+ -- if bndr' is a coercion variable; see Note [Evidence foralls]
; pure ( useful, subst2
- , bndrs ++ rule_bs, dummy_arg : rule_es
- , bndrs ++ spec_bs, dx, dummy_arg : spec_args ) }
+ , bndr' : rule_bs, dummy_arg : rule_es
+ , bndr' : spec_bs, dx, dummy_arg : spec_args ) }
-- | Binds a dictionary argument to a fresh name, to preserve sharing
=====================================
compiler/GHC/Core/Subst.hs
=====================================
@@ -590,15 +590,15 @@ substRule subst subst_ru_fn rule@(Rule { ru_bndrs = bndrs, ru_args = args
------------------
substDVarSet :: HasDebugCallStack => Subst -> DVarSet -> DVarSet
-- Apply the substitution to the vars in the set,
--- and take the shallow free vars of the result
+-- and take the (deep) free vars of the result
substDVarSet subst@(Subst _ _ tv_env cv_env) fvs
= runFVSelective isLocalVar $
strictFoldDVarSet (mappend . do_one) mempty fvs
where
do_one :: Var -> SelectiveDFV
do_one fv
- | isTyVar fv = shallowSelTypeFV (lookupVarEnv tv_env fv `orElse` mkTyVarTy fv)
- | isCoVar fv = shallowSelCoFV (lookupVarEnv cv_env fv `orElse` mkCoVarCo fv)
+ | isTyVar fv = deepSelTypeFV (lookupVarEnv tv_env fv `orElse` mkTyVarTy fv)
+ | isCoVar fv = deepSelCoFV (lookupVarEnv cv_env fv `orElse` mkCoVarCo fv)
| otherwise = exprFVs (lookupIdSubst subst fv)
------------------
=====================================
compiler/GHC/Core/TyCo/FVs.hs
=====================================
@@ -26,8 +26,9 @@ module GHC.Core.TyCo.FVs
coVarsOfCo, coVarsOfCos,
coVarsOfCoDSet, coVarsOfCosDSet,
- -- Shallow, deterministic, composable
- shallowSelTypeFV, shallowSelCoFV,
+ -- Selective, deterministic, composable
+ shallowSelTypeFV,
+ deepSelTypeFV, deepSelCoFV, deepSelUnitFV,
-- Almost devoid
almostDevoidCoVarOfCo,
@@ -50,7 +51,6 @@ module GHC.Core.TyCo.FVs
occCheckExpand,
-- * Closing over kinds
- closeOverKindsDSet,
closeOverKinds,
) where
@@ -111,6 +111,9 @@ Examples:
forall (a:(k:Type)). a {k} {k}
(a:k->Type) (b:k) {a,b} {a,b,k}
+Free variables of /terms/ (GHC.Core.FVs) are always deep; see
+Note [Free variables of an expression] in GHC.Core.FVs.
+
Note [Computing deep free variables]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -150,9 +153,10 @@ GHC.Types.Var.FV. At an occurrence of a variable (a::k)
AND add on the free vars of its kind `k`.
BUT in this latter step, start with an empty BoundVars set.
-The "start with an empty BoundVars set" is implemented in `deepUnitFV`. It's
-not /necessary/ to zap the BoundVars set, because of Invariant (NoTypeShadowing).
-But it's a tiny bit more efficient because the BoundVars set is smaller.
+The "start with an empty BoundVars set" is implemented in the `*UnitFV`
+functions. It's not /necessary/ to zap the BoundVars set, because of
+Invariant (NoTypeShadowing). But it's a tiny bit more efficient because the
+BoundVars set is smaller.
Side note: the free-variable binder would still work even without (NoTypeShadowing).
Consider:
@@ -256,39 +260,47 @@ deepCosFV :: [Coercion] -> TyCoFV
(deepTypeFV, deepTypesFV, deepCoFV, deepCosFV) = foldTyCo deepTcvFolder
deepTcvFolder :: TyCoFolder TyCoFV
+deepTcvFolder = deepFolder (deepUnitFV fvs) fvs addBndrFV
+ where fvs = deepTypeFV . varType
+
+deepFolder :: Monoid fv
+ => (TyCoVar -> fv) -- ^ an occurrence of a variable
+ -> (TyCoVar -> fv) -- ^ the free variables of a variable's type
+ -> (TyCoVar -> fv -> fv) -- ^ go under a binder
+ -> TyCoFolder fv
+-- A folder computing deep free variables; the occurrence function is one of
+-- the `*UnitFV` functions. See Note [Computing deep free variables].
+--
-- It's important that we use a one-shot EndoOS, to ensure that all
-- the free-variable finders are eta-expanded. Lacking the one-shot-ness
-- led to some big slow downs. See Note [The one-shot state monad trick]
-- in GHC.Utils.Monad
-deepTcvFolder = TyCoFolder { tcf_view = noView -- See Note [Free vars and synonyms]
- , tcf_tyvar = do_tcv, tcf_covar = do_tcv
- , tcf_hole = do_hole, tcf_lit = const mempty
- , tcf_tycobinder = addBndrFV }
- where
- do_tcv :: TyVar -> TyCoFV
- do_tcv = deepUnitFV deepTypeFV
-
- do_hole :: CoercionHole -> TyCoFV
- do_hole hole = deepTypeFV (varType (coHoleCoVar hole))
+{-# INLINE deepFolder #-}
+deepFolder occ fvs_of_type add_bndr
+ = TyCoFolder { tcf_view = noView -- See Note [Free vars and synonyms]
+ , tcf_tyvar = occ, tcf_covar = occ
+ , tcf_hole = fvs_of_type . coHoleCoVar
-- We don't collect the CoercionHole itself, but we /do/
-- need to collect the free variables of its /kind/
-- See Note [CoercionHoles and coercion free variables]
+ , tcf_lit = const mempty
+ , tcf_tycobinder = add_bndr }
-deepUnitFV :: (Type -> TyCoFV) -> TyCoVar -> TyCoFV
--- Deal with a single TyCoVar
--- Takes a function to find free vars of the kind
+deepUnitFV :: (TyCoVar -> TyCoFV) -- ^ the free variables of a variable's type
+ -> TyCoVar -> TyCoFV
+-- Deal with an occurrence of a single 'TyCoVar'
-- See Note [Computing deep free variables]
-{-# INLINE deepUnitFV #-} -- INLINE to specialise on fvs_of_kind
-deepUnitFV fvs_of_kind
+{-# INLINE deepUnitFV #-} -- INLINE to specialise on fvs_of_type
+deepUnitFV fvs_of_type
= \v -> MkFV (\bvs -> EndoOS (do_it bvs v))
where
do_it :: BoundVars -> TyCoVar -> TyCoVarSet -> TyCoVarSet
do_it bvs v acc | v `elemVarSet` bvs = acc
| v `elemVarSet` acc = acc
- | otherwise = runFVAcc (fvs_of_kind (varType v)) acc
+ | otherwise = runFVAcc (fvs_of_type v) acc
`extendVarSet` v
- -- Left-to-right: add the kind variables to the
- -- accumulator before v itself
+ -- Left-to-right: add the kind variables to the
+ -- accumulator before v itself
{- *********************************************************************
* *
@@ -389,31 +401,22 @@ deepDetCoFV :: Coercion -> DTyCoFV
(deepDetTypeFV, deepDetTypesFV, deepDetCoFV, _) = foldTyCo deepDetTcvFolder
deepDetTcvFolder :: TyCoFolder DTyCoFV
--- This one returns a /deterministic/ list
--- See `deepTcvFolder` for the general pattern
-deepDetTcvFolder
- = TyCoFolder { tcf_view = noView
- , tcf_tyvar = do_tcv, tcf_covar = do_tcv
- , tcf_hole = do_hole, tcf_lit = const mempty
- , tcf_tycobinder = addBndrFV }
- where
- do_tcv = deepDetUnitFV deepDetTypeFV
- do_hole hole = deepDetTypeFV (varType (coHoleCoVar hole))
-
-deepDetUnitFV :: (Type -> DTyCoFV) -> TyCoVar -> DTyCoFV
--- Deal with a single TyCoVar
--- Takes a function to find free vars of the kind
--- See Note [Computing deep free variables]
-deepDetUnitFV fvs_of_kind v
- = MkFV (\bvs -> EndoOS (do_it bvs))
+-- This one returns a /deterministic/ set
+deepDetTcvFolder = deepFolder (deepDetUnitFV fvs) fvs addBndrFV
+ where fvs = deepDetTypeFV . varType
+
+deepDetUnitFV :: (TyCoVar -> DTyCoFV) -- ^ the free variables of a variable's type
+ -> TyCoVar -> DTyCoFV
+-- Deterministic version of 'deepUnitFV'
+{-# INLINE deepDetUnitFV #-} -- INLINE to specialise on fvs_of_type
+deepDetUnitFV fvs_of_type
+ = \v -> MkFV (\bvs -> EndoOS (do_it bvs v))
where
- do_it :: BoundVars -> DTyCoVarSet -> DTyCoVarSet
- do_it bvs acc | v `elemVarSet` bvs = acc
- | v `elemDVarSet` acc = acc
- | otherwise = runFVAcc (fvs_of_kind (varType v)) acc
- `extendDVarSet` v
- -- Left-to-right: add the kind variables to the
- -- accumulator before v itself
+ do_it :: BoundVars -> TyCoVar -> DTyCoVarSet -> DTyCoVarSet
+ do_it bvs v acc | v `elemVarSet` bvs = acc
+ | v `elemDVarSet` acc = acc
+ | otherwise = runFVAcc (fvs_of_type v) acc
+ `extendDVarSet` v
{- *********************************************************************
* *
@@ -430,30 +433,61 @@ someTyCoVarsOfTypes interesting
= runFVSelectiveList interesting . mapUnionFV shallowSelTypeFV
shallowSelTypeFV :: Type -> SelectiveDFV
-shallowSelCoFV :: Coercion -> SelectiveDFV
-- Returns shallow free vars
-- See Note [Shallow and deep free variables]
-(shallowSelTypeFV, _, shallowSelCoFV, _) = foldTyCo selectiveTcvFolder
+(shallowSelTypeFV, _, _, _) = foldTyCo selectiveTcvFolder
selectiveTcvFolder :: TyCoFolder SelectiveDFV
-- This one takes an `InterestingVarFun`, and returns shallow free vars
-- See `shallowTcvFolder` for the general pattern
selectiveTcvFolder
= TyCoFolder { tcf_view = noView -- See Note [Free vars and synonyms]
- , tcf_tyvar = do_tcv, tcf_covar = do_tcv
+ , tcf_tyvar = shallowSelUnitFV, tcf_covar = shallowSelUnitFV
, tcf_hole = do_hole, tcf_lit = const mempty
, tcf_tycobinder = addBndrSelectiveFV }
where
- do_tcv v = MkFV (\env -> EndoOS (do_it env))
- where
- do_it (bvs,is_interesting) acc
- | v `elemVarSet` bvs = acc -- First exclude bound variables
- | not (is_interesting v) = acc -- The "selective" bit
- | v `elemDVarSet` acc = acc
- | otherwise = acc `extendDVarSet` v
-
do_hole hole = shallowSelTypeFV (varType (coHoleCoVar hole))
+shallowSelUnitFV :: TyCoVar -> SelectiveDFV
+shallowSelUnitFV v = MkFV (\env -> EndoOS (do_it env))
+ where
+ do_it (bvs,is_interesting) acc
+ | v `elemVarSet` bvs = acc -- First exclude bound variables
+ | not (is_interesting v) = acc -- The "selective" bit
+ | v `elemDVarSet` acc = acc
+ | otherwise = acc `extendDVarSet` v
+
+
+{- *********************************************************************
+* *
+ Selective, deep, deterministic free vars
+* *
+********************************************************************* -}
+
+deepSelTypeFV :: Type -> SelectiveDFV
+deepSelCoFV :: Coercion -> SelectiveDFV
+-- Returns deep free vars, selectively
+-- See Note [Shallow and deep free variables]
+(deepSelTypeFV, _, deepSelCoFV, _) = foldTyCo deepSelectiveTcvFolder
+
+deepSelectiveTcvFolder :: TyCoFolder SelectiveDFV
+deepSelectiveTcvFolder = deepFolder (deepSelUnitFV fvs) fvs addBndrSelectiveFV
+ where fvs = deepSelTypeFV . varType
+
+deepSelUnitFV :: (TyCoVar -> SelectiveDFV) -- ^ the free variables of a variable's type
+ -> TyCoVar -> SelectiveDFV
+-- ^ Selective version of 'deepUnitFV'.
+{-# INLINE deepSelUnitFV #-} -- INLINE to specialise on fvs_of_type
+deepSelUnitFV fvs_of_type
+ = \v -> MkFV (\env -> EndoOS (do_it env v))
+ where
+ do_it (bvs,is_interesting) v acc
+ | v `elemVarSet` bvs = acc
+ | not (is_interesting v) = acc
+ | v `elemDVarSet` acc = acc
+ | otherwise = runFVSelectiveAcc is_interesting (fvs_of_type v) acc
+ `extendDVarSet` v
+
{- *********************************************************************
* *
@@ -508,7 +542,7 @@ deepCoVarFolder = TyCoFolder { tcf_view = noView
-- the tyvar won't end up in the accumulator, so
-- we'd look repeatedly. Blargh.
- do_covar = deepUnitFV deepCoVarTypeFV
+ do_covar = deepUnitFV (deepCoVarTypeFV . varType)
do_hole hole = do_covar (coHoleCoVar hole)
-- We /do/ treat a CoercionHole as a free variable
@@ -540,7 +574,7 @@ deepDetCoVarFolder = TyCoFolder { tcf_view = noView
do_tyvar _ = mempty
do_covar :: CoVar -> DCoVarFV
- do_covar = deepDetUnitFV det_ty
+ do_covar = deepDetUnitFV (det_ty . varType)
do_hole hole = do_covar (coHoleCoVar hole)
@@ -558,13 +592,6 @@ closeOverKinds vs = nonDetStrictFoldVarSet do_one vs vs
where
do_one v = runFVAcc (deepTypeFV (varType v))
--- | Add the kind variables free in the kinds of the tyvars in the given set.
--- Returns a deterministic set.
-closeOverKindsDSet :: DTyVarSet -> DTyVarSet
-closeOverKindsDSet vs = nonDetStrictFoldDVarSet do_one vs vs
- where
- do_one v = runFVAcc (deepDetTypeFV (varType v))
-
{-
%************************************************************************
@@ -779,7 +806,7 @@ inj_vars_of_type :: Bool -> Type -> TyCoFV
inj_vars_of_type look_under_tfs = go
where
go ty | Just ty' <- rewriterView ty = go ty'
- go (TyVarTy v) = deepUnitFV go v
+ go (TyVarTy v) = deepUnitFV (go . varType) v
go (AppTy f a) = go f `mappend` go a
go (FunTy _ w ty1 ty2) = go w `mappend` go ty1 `mappend` go ty2
go (TyConApp tc tys) = go_tc tc tys
=====================================
compiler/GHC/Core/Type.hs
=====================================
@@ -168,7 +168,6 @@ module GHC.Core.Type (
typeSize, occCheckExpand,
-- ** Closing over kinds
- closeOverKindsDSet,
closeOverKinds,
-- * Forcing evaluation of types
=====================================
compiler/GHC/HsToCore.hs
=====================================
@@ -92,6 +92,7 @@ import GHC.Types.Id.Info
import GHC.Types.InlinePragma ( alwaysInlinePragma, competesWith )
import GHC.Types.ForeignStubs
import GHC.Types.Avail
+import GHC.Types.Var ( isNonCoVarId )
import GHC.Types.Var.Set
import GHC.Types.SrcLoc
import GHC.Types.SourceFile
@@ -479,7 +480,7 @@ dsWarnRuleShadowing fn_id
where
bndrs_set = mkVarSet bndrs
arg_ids = filterOut (`elemVarSet` bndrs_set) $
- exprsSomeFreeVarsList isId args
+ exprsSomeFreeVarsList isNonCoVarId args
check check_rules_too lhs_id
| isLocalId lhs_id || canUnfold (idUnfolding lhs_id)
=====================================
compiler/GHC/HsToCore/Binds.hs
=====================================
@@ -1014,8 +1014,7 @@ dsSpec_help poly_nm poly_id poly_rhs spec_inl orig_bndrs ds_call
is_local v = v `elemVarSet` locals
-- Find `rule_bndrs`: (S2) of Note [Desugaring new-form SPECIALISE pragmas]
- -- We have to do closeOverKinds beccause exprsSomeFreeVars is shallow
- rule_bndrs = scopedSort $ dVarSetElems $ closeOverKindsDSet $
+ rule_bndrs = scopedSort $ dVarSetElems $
exprsSomeFreeVarsDSet is_local rule_lhs_args
-- getRenamings: (S3) of Note [Desugaring new-form SPECIALISE pragmas]
=====================================
compiler/GHC/Parser.y
=====================================
@@ -1797,10 +1797,10 @@ cvars1 :: { [RecordPatSynField GhcPs] }
where_decls :: { LocatedA (OrdList (LHsDecl GhcPs), EpToken "where", AnnList) }
: 'where' '{' decls '}' {% amsA' (sLL $1 $> (thdOf3 $ unLoc $3,
epTok $1,
- AnnList (AnnListLayout (fstOf3 $ unLoc $3)) (ListBraces (epTok $2) (epTok $4)) (sndOf3 $ unLoc $3))) }
+ AnnList AnnListBraces (ListBraces (epTok $2) (epTok $4)) (sndOf3 $ unLoc $3))) }
| 'where' vocurly decls close {% amsA' (sLL $1 $3 (thdOf3 $ unLoc $3,
epTok $1,
- AnnList (AnnListLayout (fstOf3 $ unLoc $3)) ListNone (sndOf3 $ unLoc $3))) }
+ AnnList (AnnListLayout (glR $3)) ListNone (sndOf3 $ unLoc $3))) }
pattern_synonym_sig :: { LSig GhcPs }
: 'pattern' con_list '::' sigtype
@@ -1936,7 +1936,7 @@ decls :: { Located (EpaLocation, [EpToken ";"], OrdList (LHsDecl GhcPs)) }
| {- empty -} { noLoc (noAnn, [],nilOL) }
decllist :: { Located (AnnList,Located (OrdList (LHsDecl GhcPs))) }
- : '{' decls '}' { sLL $1 $> (AnnList (AnnListLayout (fstOf3 $ unLoc $2)) (ListBraces (epTok $1) (epTok $3)) (sndOf3 $ unLoc $2)
+ : '{' decls '}' { sLL $1 $> (AnnList AnnListBraces (ListBraces (epTok $1) (epTok $3)) (sndOf3 $ unLoc $2)
,sL1 $2 $ thdOf3 $ unLoc $2) }
| vocurly decls close { sL1 $2 (AnnList (AnnListLayout (fstOf3 $ unLoc $2)) ListNone (sndOf3 $ unLoc $2)
,sL1 $2 $ thdOf3 $ unLoc $2) }
@@ -1952,7 +1952,7 @@ binds :: { Located (HsLocalBinds GhcPs) }
; return (sL1 $1 $ HsValBinds (EpAnn (glR $1) (AnnList la p s) cs, noEpTok) val_binds)} }
| '{' dbinds '}' {% acs (comb3 $1 $2 $3) (\loc cs -> (L loc
- $ HsIPBinds (EpAnn (spanAsAnchor (comb3 $1 $2 $3)) (AnnList (AnnListLayout$ glR $2) (ListBraces (epTok $1) (epTok $3)) []) cs, noEpTok) (IPBinds noExtField (reverse $ unLoc $2)))) }
+ $ HsIPBinds (EpAnn (spanAsAnchor (comb3 $1 $2 $3)) (AnnList AnnListBraces (ListBraces (epTok $1) (epTok $3)) []) cs, noEpTok) (IPBinds noExtField (reverse $ unLoc $2)))) }
| vocurly dbinds close {% acs (gl $2) (\loc cs -> (L loc
$ HsIPBinds (EpAnn (glR $1) (AnnList (AnnListLayout $ glR $2) ListNone []) cs, noEpTok) (IPBinds noExtField (reverse $ unLoc $2)))) }
@@ -3543,12 +3543,12 @@ guardquals1 :: { Located [LStmt GhcPs (LHsExpr GhcPs)] }
altslist(PATS) :: { forall b. DisambECP b => PV (LocatedA ([LMatch GhcPs (LocatedA b)], AnnList)) }
: '{' alts(PATS) '}' { $2 >>= \ $2 -> amsA'
(sLL $1 $> (reverse (snd $ unLoc $2),
- (AnnList (AnnListLayout $ glR $2) (ListBraces (epTok $1) (epTok $3)) (fst $ unLoc $2)))) }
+ (AnnList AnnListBraces (ListBraces (epTok $1) (epTok $3)) (fst $ unLoc $2)))) }
| vocurly alts(PATS) close { $2 >>= \ $2 -> amsA'
(L (getLoc $2) (reverse (snd $ unLoc $2),
(AnnList (AnnListLayout $ glR $2) ListNone (fst $ unLoc $2)))) }
- | '{' '}' { amsA' (sLL $1 $> ([], (AnnList AnnListNoLayout (ListBraces (epTok $1) (epTok $2)) []))) }
- | vocurly close { return $ noLocA ([], noAnn) }
+ | '{' '}' { amsA' (sLL $1 $> ([], (AnnList AnnListBraces (ListBraces (epTok $1) (epTok $2)) []))) }
+ | vocurly close { return $ noLocA ([], AnnList (AnnListLayout $ glR $1) ListNone []) }
alts(PATS) :: { forall b. DisambECP b => PV (Located ([EpToken ";"],[LMatch GhcPs (LocatedA b)])) }
: alts1(PATS) { $1 >>= \ $1 -> return $
@@ -3657,7 +3657,7 @@ apat : aexp {% (checkPattern <=< runPV) (unECP $1) }
stmtlist :: { forall b. DisambECP b => PV (LocatedA (AnnList, Located [LocatedA (Stmt GhcPs (LocatedA b))])) }
: '{' stmts '}' { $2 >>= \ $2 ->
- amsA' (sLL $1 $> (AnnList (AnnListLayout (spanAsAnchor $ stmtsLoc $2)) (ListBraces (epTok $1) (epTok $3)) (fromOL $ fst $ unLoc $2)
+ amsA' (sLL $1 $> (AnnList AnnListBraces (ListBraces (epTok $1) (epTok $3)) (fromOL $ fst $ unLoc $2)
, sL1 $2 $ reverse $ snd $ unLoc $2))}
| vocurly stmts close { $2 >>= \ $2 ->
amsA' (L (stmtsLoc $2) (AnnList (AnnListLayout (spanAsAnchor $ stmtsLoc $2)) ListNone (fromOL $ fst $ unLoc $2)
=====================================
compiler/GHC/Tc/Utils/TcType.hs
=====================================
@@ -183,7 +183,7 @@ module GHC.Tc.Utils.TcType (
coreView,
tyCoVarsOfType, tyCoVarsOfTypes, closeOverKinds,
- tyCoVarsOfTypeDSet, tyCoVarsOfTypesDSet, closeOverKindsDSet,
+ tyCoVarsOfTypeDSet, tyCoVarsOfTypesDSet,
tyCoVarsOfTypeList, tyCoVarsOfTypesList,
noFreeVarsOfType,
=====================================
compiler/GHC/Types/Var/FV.hs
=====================================
@@ -6,7 +6,7 @@ module GHC.Types.Var.FV (
BoundVars, VarSetFV, DVarSetFV, SelectiveDFV,
TyCoFV, DTyCoFV,
runFVTop, runFVAcc, runTyCoVars, runTyCoVarsDSet,
- runFVSelective, runFVSelectiveList, runFVSelectiveSet,
+ runFVSelective, runFVSelectiveAcc, runFVSelectiveList, runFVSelectiveSet,
InterestingVarFun,
updEnvFV, addBndrFV, addBndrsFV, addBndrSelectiveFV, addBndrsSelectiveFV,
@@ -225,8 +225,11 @@ runTyCoVarsDSet :: DTyCoFV -> DTyCoVarSet
runTyCoVarsDSet f = runFVAcc f emptyDVarSet
runFVSelective :: InterestingVarFun -> SelectiveDFV -> DVarSet
-runFVSelective interesting f
- = runEndoOS (runFV f (emptyVarSet, interesting)) emptyDVarSet
+runFVSelective interesting f = runFVSelectiveAcc interesting f emptyDVarSet
+
+runFVSelectiveAcc :: InterestingVarFun -> SelectiveDFV -> DVarSet -> DVarSet
+-- Add the interesting free variables to the accumulator
+runFVSelectiveAcc interesting f = runEndoOS (runFV f (emptyVarSet, interesting))
runFVSelectiveList :: InterestingVarFun -> SelectiveDFV -> [Var]
runFVSelectiveList interesting f = dVarSetElems (runFVSelective interesting f)
=====================================
libraries/base/tests/Memo1.lhs
=====================================
@@ -13,10 +13,10 @@ module Memo1
where
import System.Mem.StableName ( StableName, makeStableName, hashStableName )
-import System.Mem.Weak ( Weak, mkWeakPtr, mkWeak, deRefWeak, finalize )
+import System.Mem.Weak ( Weak, mkWeak, deRefWeak, finalize )
import Data.Array.IO ( IOArray, newArray, readArray, writeArray )
import System.IO.Unsafe ( unsafePerformIO )
-import Control.Concurrent.MVar ( MVar, newMVar, putMVar, takeMVar )
+import Control.Concurrent.MVar ( MVar, newMVar, putMVar, takeMVar, mkWeakMVar )
\end{code}
-----------------------------------------------------------------------------
@@ -78,7 +78,7 @@ lazyMemoSized size f =
let (table,weak) = unsafePerformIO (
do { tbl <- newArray (0,size) []
; mvar <- newMVar (size,tbl)
- ; weak <- mkWeakPtr mvar (Just (table_finalizer tbl size))
+ ; weak <- mkWeakMVar mvar (table_finalizer tbl size)
; return (mvar,weak)
})
in memo' f table weak
=====================================
libraries/base/tests/Memo2.lhs
=====================================
@@ -13,10 +13,10 @@ module Memo2
where
import System.Mem.StableName ( StableName, makeStableName, hashStableName )
-import System.Mem.Weak ( Weak, mkWeakPtr, mkWeak, deRefWeak, finalize )
+import System.Mem.Weak ( Weak, mkWeak, deRefWeak, finalize )
import Data.Array.IO ( IOArray, newArray, readArray, writeArray )
import System.IO.Unsafe ( unsafePerformIO )
-import Control.Concurrent.MVar ( MVar, newMVar, putMVar, takeMVar )
+import Control.Concurrent.MVar ( MVar, newMVar, putMVar, takeMVar, mkWeakMVar )
\end{code}
-----------------------------------------------------------------------------
@@ -78,7 +78,7 @@ lazyMemoSized size f =
let (table,weak) = unsafePerformIO (
do { tbl <- newArray (0,size) []
; mvar <- newMVar (size,tbl)
- ; weak <- mkWeakPtr mvar (Just (table_finalizer tbl size))
+ ; weak <- mkWeakMVar mvar (table_finalizer tbl size)
; return (mvar,weak)
})
in memo' f table weak
=====================================
libraries/base/tests/all.T
=====================================
@@ -135,8 +135,7 @@ test('list003', when(fast(), skip), compile_and_run, [''])
test('isSuffixOf', normal, compile_and_run, [''])
test('memo001', [extra_files(['Memo1.lhs']),
- extra_run_opts('+RTS -A10k -RTS'),
- expect_broken_for(27396, opt_ways)], multimod_compile_and_run,
+ extra_run_opts('+RTS -A10k -RTS')], multimod_compile_and_run,
['memo001', ''])
test('memo002', [extra_files(['Memo2.lhs']),
=====================================
testsuite/tests/parser/should_compile/DumpSemis.stderr
=====================================
@@ -364,8 +364,7 @@
((,)
(Right
(AnnList
- (AnnListLayout
- (EpaSpan { DumpSemis.hs:11:8-13 }))
+ (AnnListBraces)
(ListBraces
(EpTok (EpaSpan { DumpSemis.hs:11:6 }))
(EpTok (EpaSpan { DumpSemis.hs:11:15 })))
@@ -627,8 +626,7 @@
((,)
(Right
(AnnList
- (AnnListLayout
- (EpaSpan { DumpSemis.hs:(16,5)-(18,5) }))
+ (AnnListBraces)
(ListBraces
(EpTok (EpaSpan { DumpSemis.hs:16:3 }))
(EpTok (EpaSpan { DumpSemis.hs:19:3 })))
@@ -880,8 +878,7 @@
((,)
(Right
(AnnList
- (AnnListLayout
- (EpaSpan { DumpSemis.hs:22:12-28 }))
+ (AnnListBraces)
(ListBraces
(EpTok (EpaSpan { DumpSemis.hs:22:10 }))
(EpTok (EpaSpan { DumpSemis.hs:22:30 })))
@@ -1936,8 +1933,7 @@
(EpAnn
(EpaSpan { DumpSemis.hs:34:13-31 })
(AnnList
- (AnnListLayout
- (EpaSpan { DumpSemis.hs:34:18-30 }))
+ (AnnListBraces)
(ListBraces
(EpTok (EpaSpan { DumpSemis.hs:34:13 }))
(EpTok (EpaSpan { DumpSemis.hs:34:31 })))
@@ -2333,8 +2329,7 @@
((,)
(FromSource)
(AnnList
- (AnnListLayout
- (EpaSpan { DumpSemis.hs:(38,6)-(43,13) }))
+ (AnnListBraces)
(ListBraces
(EpTok (EpaSpan { DumpSemis.hs:38:4 }))
(EpTok (EpaSpan { DumpSemis.hs:44:4 })))
=====================================
testsuite/tests/simplCore/should_compile/T27936.hs
=====================================
@@ -0,0 +1,9 @@
+{-# LANGUAGE GADTs, ViewPatterns, RankNTypes #-}
+{-# OPTIONS_GHC -fno-opt-coercion #-}
+module T27936 where
+
+data G a where
+ MkG :: G Int
+
+f :: G a -> a -> Int -> Int
+f MkG v (((\x -> (v + 1, x)) :: forall b. b -> (Int, b)) -> (y, _)) = y
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -627,3 +627,5 @@ test('T27749',
compile, ['-O -g3 -ddump-simpl -dsuppress-uniques'])
test('T27629', only_ways(['optasm']), makefile_test, ['T27629'])
+
+test('T27936', normal, compile, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b877a9b0eacc082eccf51b70b8b4a9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b877a9b0eacc082eccf51b70b8b4a9…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc] Pushed new branch wip/jeltsch/smaller-pit.with-haddock-hug-lookup
by Wolfgang Jeltsch (@jeltsch) 14 Oct '26
by Wolfgang Jeltsch (@jeltsch) 14 Oct '26
14 Oct '26
Wolfgang Jeltsch pushed new branch wip/jeltsch/smaller-pit.with-haddock-hug-lookup at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/jeltsch/smaller-pit.with-hadd…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/rafl/meaningful-main-return] Implement MeaningfulMainReturn
by Florian Ragwitz (@rafl) 14 Oct '26
by Florian Ragwitz (@rafl) 14 Oct '26
14 Oct '26
Florian Ragwitz pushed to branch wip/rafl/meaningful-main-return at Glasgow Haskell Compiler / GHC
Commits:
2a1fe278 by Florian Ragwitz at 2026-10-14T14:18:49-07:00
Implement MeaningfulMainReturn
As per ghc-proposal#631, with one small adjustment explained in the comments.
Fixes #24848.
- - - - -
44 changed files:
- + changelog.d/MeaningfulMainReturn
- compiler/GHC/Builtin/KnownOccs.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Types/Error/Codes.hs
- + docs/users_guide/exts/meaningful_main_return.rst
- docs/users_guide/exts/misc.rst
- docs/users_guide/using-warnings.rst
- libraries/base/src/GHC/Essentials.hs
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- testsuite/tests/driver/T4437.hs
- + testsuite/tests/ghc-e/should_run/T9086.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- + testsuite/tests/meaningful-main-return/Imported.hs
- + testsuite/tests/meaningful-main-return/MainReturn_constrained_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_alias_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_bottom_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_bottom_enabled_run.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_success_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_always_exit_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_invalid_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_invalid_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_stuck_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_stuck_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_invalid_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_invalid_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_wrapped_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_int_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_int_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_newtype_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_newtype_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_typeapp_disabled.stderr
- + testsuite/tests/meaningful-main-return/MeaningfulMainReturn.hs
- + testsuite/tests/meaningful-main-return/all.T
- testsuite/tests/parser/should_compile/T7476/T7476.hs
- + testsuite/tests/typecheck/should_compile/tc104.stderr
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2a1fe2789a1810d565f508d5846fa9f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2a1fe2789a1810d565f508d5846fa9f…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/int-index/curried-ctxts] 56 commits: Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
by Vladislav Zavialov (@int-index) 14 Oct '26
by Vladislav Zavialov (@int-index) 14 Oct '26
14 Oct '26
Vladislav Zavialov pushed to branch wip/int-index/curried-ctxts at Glasgow Haskell Compiler / GHC
Commits:
545fd4fb by ARATA Mizuki at 2026-09-22T15:03:24-04:00
Change the C types of hs_{bitrev,bswap}{16,32} to match the Haskell types
bitReverse{16,32}# and byteSwap{16,32}# have the type
Word# -> Word#, but their C correspondents took and
returned StgWord{16,32}.
The mismatch on bitReverse16# led to the problem reported
in #27299. Although no similar issue is reported for
bitReverse32# and byteSwap{16,32}#, it seemed wise to
change them proactively.
This commit fixes the mismatch by changing the C type.
Fixes #27299
- - - - -
bf17f289 by fendor at 2026-09-22T15:04:05-04:00
Don't lose instances from shadowed imported modules with the same name
When we look for instances below the current module, we need to check
the unit id as well when we check for whether the module is the current
module, otherwise we ignore modules we import that have the same name as
the import module.
Adds regression test.
- - - - -
53eead15 by Wolfgang Jeltsch at 2026-09-24T20:12:03-04:00
Correct the documentation of `explicitUnits`
Resolves #27787.
- - - - -
35bf6f4b by Simon Jakobi at 2026-09-24T20:12:49-04:00
Remove stale specHeader bullet from Note [Don't make fillers for constraint types]
The Note said that Specialise.specHeader also calls mkAbsentFiller.
abfc224a27c removed that call: the specialiser no longer drops dead
arguments at all, see Note [Do not drop dead args from specialisations]
in GHC.Core.Opt.Specialise.
Assisted-by: Claude Fable 5.1
- - - - -
1abef1ef by Wolfgang Jeltsch at 2026-09-25T17:02:07-04:00
Improve the `mhu-closure` makefile
- - - - -
a79a68ea by Wolfgang Jeltsch at 2026-09-25T17:02:07-04:00
Make `ghci-multi` hide all unneeded packages
- - - - -
d6e72450 by Wolfgang Jeltsch at 2026-09-25T17:02:07-04:00
Improve the definition of the home unit closure property
- - - - -
c9a2766d by Wolfgang Jeltsch at 2026-09-25T17:02:07-04:00
Re-implement the home unit closure check
Compared to the previous implementation, the new one has the following
advantages:
* It is correct.
- It distinguishes between units that have the same unit ID but
different ABI hashes.
- When `-hide-all-packages` is not used, it considers as home unit
dependencies also units that are made implicitly available
because they are in the package database.
* It seems to be faster in usual settings.
- In particular, it does not have a preparation phase in which it
merges the dependency information from all home units, so that
its running time does not grow linearly with the size of the
package database in normal Cabal scenarios.
* It is (hopefully) clearer.
* It is better documented.
- - - - -
fa96acf8 by Wolfgang Jeltsch at 2026-09-25T17:02:07-04:00
Remove erroneous GHC flag in `hadrian-multi`
The flag was `-Werror=-Wno-error=incomplete-record-selectors`. Its
purpose was to permit incomplete record selectors, but because of the
illegal combination of `-Werror=` and `-Wno-error` it was ignored,
without any negative consequences.
- - - - -
9f48a5b9 by Alan Zimmerman at 2026-09-25T17:02:50-04:00
EPA: Add specific layout field to AnnList
Up to now AnnList has effectively served to represent lists of things
having layout, regardless of whether they do or not.
In Haskell, layout is optional in many places, as there is also an
alternative syntax using braces and semi-colons, which is free-form.
This commit introduces AnnListLayout, a data structure capturing this
distinction.
It is deliberately set up similarly to EpLayout, so that these two can
be merged in time.
The transition is done mechanically, where AnnListBraces is not used
yet, the original Nothing case maps to AnnListNoLayout, and the Just
case to AnnListLayout.
Later commits will fine tune these against the actual parser layout.
- - - - -
234bab08 by Vladislav Zavialov at 2026-09-29T17:22:54-04:00
Add regression test for #7803
Commit 2effe18ab5, first shipped with GHC 8.2.1, fixed #7803 "Superclass
methods are left unspecialized".
This change turns the example from the ticket description into a regression
test, checking that foo1 is fully specialised at Double, with no calls to the
overloaded exp5Tail.
Closes #7803
Assisted-by: Claude Opus 5
- - - - -
c406135c by Andreas Klebinger at 2026-10-01T06:57:28-04:00
RTS: Update flag parsing/handling:
Using 0 as argument to any of these flags now resets the flags setting to default:
- ``-n0`` disables nursery chunking.
- ``-K0`` (or a bare ``-K``) removes the stack size limit.
- ``-M0`` removes the heap size limit.
- ``-H0`` resets the suggested heap size, including the nursery scaling set by ``-H``.
- ``-AL0`` makes the large object allocation limit follow ``-A`` again.
GC Generations are now limited to 64.
-n larger than -A now emits a warning and disables chunking.
Fixes #27830 #27829
- - - - -
984ee82b by Andreas Klebinger at 2026-10-01T06:58:10-04:00
Fix MultiLayerModules timeout multiplier.
We accidentally used the compile multiplier for ghci commands which
use the run timeout setting to set the timeout.
Fixes #26263 and #27796.
- - - - -
50a9cf26 by Andreas Klebinger at 2026-10-01T06:58:10-04:00
testsuite: Include runtime in JUnit report.
- - - - -
e358619f by Alan Zimmerman at 2026-10-01T06:59:01-04:00
EPA: Use EpaLocation in EpVirtualBraces
Haddock processing uses EpLayout.EpVirtualBraces to record the current
layout column, for allocating haddock comments correctly.
For exact printing, we need the line as well as the col, so we know
how many lines to skip when the indented code block starts.
This commit updates EpLayout.EpVirtualBraces so that it carries an
EpaLocation instead of just the Int column, to allow it to be used for
both purposes.
It is a simple mechanical change, with no other impact, but it allows
us to use EpLayout instead of AnnListLayout in AnnList, in the next
commit in this series.
- - - - -
1d2a26ee by Andrew Lelechenko at 2026-10-01T20:22:04-04:00
Remove bitSize from MINIMAL pragma of class Bits
Cf. https://github.com/haskell/core-libraries-committee/issues/441
The function is deprecated for 12 years and has a default implementation,
yet it was never removed from the MINIMAL pragma, putting library authors
in a very awkward position. Let's finally remove bitSize from MINIMAL.
- - - - -
3cc21e4c by Hannes Siebenhandl at 2026-10-01T20:22:59-04:00
Add regression test for #27641
- - - - -
c35096f5 by Hannes Siebenhandl at 2026-10-01T20:23:00-04:00
Don't `:add` modules the loader will reject
Only home modules can be actually added to the loader context, thus we
only accept the module if it belongs to a home unit.
- - - - -
a563cb27 by Simon Jakobi at 2026-10-02T17:37:36-04:00
ci: accept modified changelog.d entries in lint-changelog
The changelog guide says to extend an existing entry rather than add a
new one when the feature is already documented. lint_changelog only
counted added files, so such MRs failed before the validator ran.
Fixes #27779.
Assisted-by: Claude Fable 5.1
- - - - -
03082cd4 by Simon Jakobi at 2026-10-02T17:38:17-04:00
changelog.d: Fix warning flag name in the semaphore-v2 entry
The entry refers to -Wsemaphore-version-mismatch, which does not exist.
The warning GHC emits when it cannot use a -jsem semaphore, including
on a protocol version mismatch, is -Wsemaphore-open-failure.
Context: !15729, #25087
Assisted-by: Claude Fable 5.1
- - - - -
a93705ee by Simon Jakobi at 2026-10-02T17:38:17-04:00
changelog.d: Fix the CLC proposal link in the T27455 entry
The entry used the Sphinx :ref: role with a URL as its target. :ref:
resolves only internal labels, so the generated release notes would
show the proposal name without a link. Use the plain hyperlink form
like the other entries.
Context: !16274, #27455
Assisted-by: Claude Fable 5.1
- - - - -
54381079 by Hannes Siebenhandl at 2026-10-02T17:39:01-04:00
Extend the `TrustOverlay` for wired-in units
The TrustOverlay only contained the `UnitId` of all on-disk units.
However, wired-in units are referred to by their wired-in unit id, which
is not the same as the on-disk unit id.
Thus, trust checks for wired-in units failed because the lookup was
using the wired-in unit, which wasn't present in the `TrustOverlay`.
We fix #27834, by copying the trust info for wired-in unit ids.
- - - - -
f8cfb1a5 by Hécate Kleidukos at 2026-10-04T19:36:39+02:00
[CLC 341] Strict variants of mutable types
This commit is the implementation of CLC Proposal 341
https://github.com/haskell/core-libraries-committee/issues/341
- - - - -
575c4bc6 by Rodrigo Mesquita at 2026-10-05T12:32:02-04:00
ttg: HsModuleName in the AST, ModuleName in GHC
This commit makes the AST fully independent from GHC by parsing a
"module name" as an `HsModuleName (= HText)` rather than constructing an
`ModuleName (= FastString)` straight away.
In the GHC side, everything remains as a `ModuleName`. We turn AST
`HsModuleName`s into fast strings with the cheap `mkFastStringShortText`
when we process the AST for manipulation within the compiler.
There are no performance regressions introduced by this approach.
This is the final piece of #21592
Alternative plans were discussed in
gitlab.haskell.org/ghc/ghc/-/merge_requests/16546#note_694647,
but the Simon suggested one won in simplicity and performance when
compared against my attempt at implementing my original plan of having
a family `ModuleNameP`.
- - - - -
b3b89d32 by mangoiv at 2026-10-05T22:03:32-04:00
hadrian: Persist the used flavour name in the build root (#20650)
This executes the idea proposed in #20650, teaching Hadrian to persist
the flavour used to build a build root. This both makes use of multiple
build roots more ergonomic (as the user no longer needs to repeat
themselves) and avoids a tiresome foot-gun (forgetting to specify a
flavour, often wholly invalidating a build root).
Closes #20650.
Co-authored-by: Sylvain Henry <sylvain(a)haskus.fr>
- - - - -
f977837b by mangoiv at 2026-10-05T22:04:21-04:00
configure: fix sed script and subst tooldir script
Fixes #27672
Adds sanity checking for SUBST_TOOLDIR
Metric Decrease:
LinkableUsage01
MultiLayerModulesTH_OneShot
T10547
T12234
T12425
T13035
T13820
T18140
T18730
T18923
T9198
TcPlugin_RewritePerf
mhu-perf
- - - - -
f1cb08be by Hannes Siebenhandl at 2026-10-05T22:05:03-04:00
Prepend in-memory unit database for backpack
The packageDbFlags are stored in reverse order. Thus, prepending will
ensure that the in-memory unit database is the last item on the unit
database stack.
Further, the in-memory unit database needs to be able to shadow units
from earlier unit databases in the unit database stack.
Moreover, a `-clear-package-db` would remove the in-memory database if
it weren't the last item on the stack.
Closes #27835
- - - - -
8d49ed42 by Kazu Yamamoto at 2026-10-06T19:37:25-04:00
Do not leave standard file descriptors free at startup (#24450)
A process may be started with stdout closed -- `prog >&-` from a shell does
exactly that. Nothing then reserves descriptor 1, and open(), pipe() and
socket() hand out the lowest free descriptor, so the next descriptor the
runtime creates for itself takes it: the ticker's pipe, or a capability's IO
manager control pipe.
'GHC.Internal.IO.StdHandles.stdout' is a CAF, built the first time the program
writes to stdout, which is long after that has happened. It builds a 'Handle'
over descriptor 1, which now belongs to the runtime, and nothing reports an
error because the descriptor is perfectly good. The program then writes its
output into the runtime's own plumbing.
What that looks like from the outside is a hang. The descriptor the Handle has
taken over is the read end of a pipe, so poll() for POLLOUT on it never says
yes and epoll_ctl() accepts a registration for it; the thread waiting to write
blocks for ever. Closing the Handle at exit closes the runtime's descriptor,
which is worse: the ticker then fails on every tick.
'hs_init_ghc' now opens /dev/null onto whichever of descriptors 0, 1 and 2 are
closed, before the runtime creates any descriptor of its own. Each is opened
for the access that descriptor would normally have, read-only for 0 and
write-only for 1 and 2, so that writing to 'stdin' or reading from 'stdout'
still fails rather than quietly succeeding against /dev/null. See
Note [Standard file descriptors must be open].
Moving only the descriptors the runtime opens would not do: the first file the
program itself opened would land on the free number instead. The fix has to
leave no free number. A program run this way therefore finds stdout connected
to /dev/null rather than failing with EBADF on the first write, which is what
such a program would get from most other language runtimes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply(a)anthropic.com>
- - - - -
65bcf9e9 by Simon Jakobi at 2026-10-06T19:38:09-04:00
changelog: Repair the sentence describing #27477
The description read "programs using could crash", the object of
"using" having been lost. The synopsis already says which programs are
affected, so drop the dangling word.
Assisted-by: Claude Fable 5.1
- - - - -
15ece296 by mangoiv at 2026-10-08T15:14:56-04:00
ci: move hadrian/ghci into the lint category so it can be picked up by more runners
Fixes #27817
- - - - -
c0823135 by mangoiv at 2026-10-08T15:14:56-04:00
ci: make lint-adjacent jobs into platform independent
- move lint jobs into lint-anyarch tag
- unify lint jobs under the same platform independent container
- - - - -
f76464cf by Zubin Duggal at 2026-10-08T15:15:39-04:00
DmdAnal: Make AbsDmd neutral in maxDmd
fixes #27845
- - - - -
ffa56ae4 by sheaf at 2026-10-09T17:15:59+02:00
Preserve sign of zero when parsing -0.0#
This commit leverages the recently added GHC.Types.Literal.Floating
module in order to preserve the sign of negative zero from
source-written floating-point literals.
Fixes #27545
- - - - -
d538cac9 by Facundo Domínguez at 2026-10-09T20:26:38-04:00
Propagate annotations to simple interfaces
This allows annotations to be visible to plugins when run by
haddock. The LiquidHaskell plugin needs the annotations, in particular.
Fixes #26761
- - - - -
32c4f4ab by meooow25 at 2026-10-09T20:27:28-04:00
Bump containers submodule to 0.8.1
And fix affected tests.
* T4086a: containers depends on template-haskell-lift now instead of
template-haskell.
* T22611: Updated to be less dependent on containers internals.
- - - - -
c786065e by sheaf at 2026-10-09T20:28:20-04:00
Use an explicit pattern match in toIfaceIdDetails
The old wildcard pattern let this code bit rot: it did not properly account
for recently added 'IdDetails' such as 'RepPolyId', which resulted in
spurious 'pprTrace' messages that could even pollute HLS sessions.
Fixes #23785
- - - - -
e7cacf59 by sheaf at 2026-10-09T20:29:09-04:00
Take into account ifKind in freeNamesIfDecl
Commit 3c2f4bb4 added the 'ifKind' field to various constructors
of 'IfaceDecl', which preserves the original kind (before type synonym
expansion) for better error messages.
However, that commit forgot to update 'freeNamesIfDecl' correspondingly.
This could result in a "urk! lookup local fingerpring" crash when e.g.
a type's kind uses a type synonym defined later, as we failed to add a
dependency on the type synonym during dependency analysis.
Fixes #27916
- - - - -
41e80f41 by Simon Peyton Jones at 2026-10-11T14:38:51-04:00
Simplify the error-suppression mechanism in GHC.Tc.Errors
In `GHC.Tc.Errors.reportWanteds` we suppress some errors in favour of
others. But the mechanism had grown crufty, and #27331 exposed a bug.
This MR makes it simpler and more uniform, by doing everything via
the `ei_suppress` field of the ErrorItem.
Claude then found another closely-related bug (see the review linked
on !16564). That bug is immortalised in new test T18851d.
I'm still not happy with `ignoreConstraint` but we can worry about
that another day; I have not touched it.
Main changes
* Instead of /predicting/ when an error will be reported, we set
`cec_error_reported` when an error is /actually/ reported. (I renamed
it from `cec_suppress` to reflect this change.)
Now errors are suppressed only when a preceding error has actually been
reported. Simpler and more robust.
See `Note [cec_error_reported: suppressing less-serious errors]`
The big changes are in `reportWanteds` which looks very different.
* New `Note [ei_suppress: suppressing confusing errors]` describes the
(quite separate) `ei_suppress` mechanism for suppressing confusing
errors, mainly arising from non-empty rewriter sets
* In `tryTypeClassDefaulting`, instead of switching off type-class defaulting
if there is an insoluble /anywhere/, we just switch it off locally when
we find an insoluble sub-tree. See Note [When to do type-class defaulting]
and (W5) in Note [ApproximateWC]
* Greatly simplify `insolubleWantedCt`.
* I made type-class-defaulting be a bit more eager, only switched off when
a peer or ancestor (but not child) constraint is insoluble. See
Note [When to do type-class defaulting].
Small refactorings
* Rename `askNoErrs` to `askErrsFound` and flip its polarity
* The code for "check if ei_suppress is true of all items" code is
moved to `mkErrorItems` rather than in the large `reportWanteds`.
* Code for `has_gadt_match` moves to `mkGivenErrorReporter`, rather than
polluting the large `reportWanteds`.
* Many tests with `-fdefer-type-errors` get more warnings, especially
about ambiguous (Num a) constraints. This is by-design: see
Note [Always warn with -fdefer-type-errors]. Previously GHC was not
honouring this Note but now it is, hence the extra errors.
- - - - -
f217fc31 by Cheng Shao at 2026-10-11T14:39:33-04:00
compiler: ensure cross ghc --info output target unit ids
Previously, for cross ghcs, the base/ghc/ghc-internal unit ids in
--info output do not match the target unit ids reported by ghc-pkg,
breaking cross ghc release builds with hash-unit-ids when being used
with cabal 3.18. This patch fixes it by making --info output target
unit ids. Fixes #27919.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
d07a5176 by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Remove the Eq and Ord instances for ForAllTyFlag
In Note [Comparing visibility] in GHC.Core.TyCo.Compare we read that
"we always compare ForAllTyFlags with `eqForAllVis` or `cmpForAllVis`"
But alas there was an Eq and Ord instance for ForAllTyFlag, which made it
impossible to check this claim. So I made these changes:
* Move the definition of ForAllTyFlag and its related functions from
L.H.S.Specificity (where it did not belong, since L.H.S didn't use it)
into GHC.Types.Var.
* Remove the Eq and Ord instances for ForAllTyFlag
* Deal with the fallout, by using `eqForAllVis` or related functions.
* In interface files we use IfaceType as a key for a de-deduplication map
See Note [Deduplication during iface binary serialisation]
in GHC.Iface.Binary. For this we need /exact/ comparison, so we use a
newtype wrapper for IfaceForAllTyFlag, and give use `cmpForAllTyFlagExactly`
to implement its Ord instance. Tiresome but easy.
* Rename `toIfaceForAllBndrs` to `toIfaceForAllTyBndrs`
- - - - -
ea5c054d by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Refactor type and coercion substitution
This MR refactors type and coercion substitution so that they use
TyCoMapper, rather than hand-rolled code. Fundamentally it's a simple
idea, but I had to do quite a bit of refactoring to make it fly.
I got Claude to help me this this refactoring, but I paid careful
attention to every line of code.
Main changes:
* New module GHC.Core.TyCo.Make which defines TyCoMapper, and a bunch of other
simple "smart constructors" for types and coercions. See
GHC.Core.TyCo.Rep Note [The Type-related module hierarchy], esp (TRM1)
* The new TyCoMapper has new fields `tcm_tcapp_ty` and `tcm_tcapp_co` to handle
type-constructor applications. These replace `tcm_tycon`.
* Rewrite GHC.Core.TyCo.Subst to use TyCoMapper
* Rewrite GHC.Core.Type.expandTypeSynonyms to use TyCoMapper.
* Implement `seqType` and `seqCo` with TyCoFolder. To to this I had to add
a `tcf_lit` field to TyCoFolder.
* A new module GHC.Utils.StrictIdentity to define a strict identity monad,
which itself is used for
substTyCoMapper :: TyCoMapper Subst StrictIdentity
* I removed an apparently-unused instance for Binary Levity
Refactoring `seq` functions
* In GHC.Core.Seq, redefine `seqOneShot`, `seqRuleInfo`, and friends to return
`SeqResult`, a new type defined in GHC.Types.Baseic, rather than `()`. We
can define a Monoid instance for `SeqResult` that does the right thing.
* This has knock-on effects across the compiler.
- - - - -
34165e23 by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Refactor TyCoMapper to take a single monad; add StrictReaderT
TyCoMapper used to be parameterised over both an environment and a
monad, with fields like
tcm_tyvar :: env -> TyVar -> m Type
Now it is parameterised over just the monad:
tcm_tyvar :: TyVar -> m Type
If the mapping needs an environment, `m` is a reader monad over that
environment. Many uses (e.g. zonkTcTypeMapper, swizzleMapper) need no
environment at all, and used to pass a dummy (). The binder field
becomes
tcm_tycobinder :: forall r. TyCoVar -> ForAllTyFlag
-> (TyCoVar -> m r) -> m r
and runs the continuation in the extended environment. mapTyCoX is gone;
only mapTyCo remains.
To make this efficient, the reader monad must use the one-shot trick and
be strict in the environment. So:
* New module GHC.Utils.Monad.StrictReader defines
newtype StrictReaderT r m a
with hand-written instances. The builder of the pattern synonym
`StrictReaderT` is a smart constructor that adds both `oneShot` and a
bang on the environment, so every StrictReaderT computation is strict
in the environment. See Note [Instances for StrictReaderT].
* ZonkT becomes type ZonkT = StrictReaderT ZonkEnv
ZonkM becomes type ZonkM = StrictReaderT ZonkGblEnv IO
replacing their own hand-written instances.
* Substitution uses
type SubstM = StrictReaderT Subst StrictIdentity
substTyCoMapper :: TyCoMapper SubstM
and similarly expandTypeSynonymMapper.
* zonk_tycomapper :: TyCoMapper (ZonkT TcM) is now much simpler.
* swizzleMapper uses StrictIdentity rather than Identity.
* Module renaming, so that the strict monads are all peers in GHC.Utils.Monad:
GHC.Utils.StrictIdentity ==> GHC.Utils.Monad.StrictIdentity
GHC.Utils.Monad.State.Strict ==> GHC.Utils.Monad.StrictState
alongside the new GHC.Utils.Monad.StrictReader.
Co-Authored-By: Claude Opus 5.5 <noreply(a)anthropic.com>
- - - - -
c0299e15 by Simon Jakobi at 2026-10-13T18:11:23-04:00
testsuite: Line-buffer the driver's stdout
Python block-buffers stdout when it is a pipe. This is the case for
example in CI. As a result there is often no indication of progress at
all until the run ends.
To fix this, we configure it explicitly to use line buffering instead.
stderr is reconfigured too, for consistency: Python line-buffers it by
default since 3.9.
The type-ignores are for mypy, which types these handles as TextIO — an
interface without reconfigure.
Fixes #12934.
Assisted-by: Claude Fable 5
- - - - -
9b5beaa2 by Florian Ragwitz at 2026-10-13T18:12:05-04:00
hpc: Improve coverage semantics for instance methods and instances
Users care about which of their explicitly written methods are or aren't
covered, not whether all of the inherited methods are covered as well. Those
should be covered where they are implemented.
We therefore skip generating top-level boxes for inherited methods which will
appear as uncovered with no clear indication as to why, and no way to fix other
than exercising code the user has not written.
Previously, top-level boxes for those inherited methods would use the instance
head as their source span. Now that those boxes are gone, we can use that
source span for another purpose:
We introduce a new top-level box for each class instance with its instance head
as the source span, and use that to indicate whether or not an instance has
been covered at all.
We do this by making any method of the instance, inherited/generated or
otherwise, tick the box for the instance head. Excluded from this are
methodless classes, which could never be covered using the current mechanism.
This could be improved upon further.
These changes apply to ticking for program coverage only, and don't affect
source notes. Additionally, we update the scope of record selector ticking to
be limited to program coverage as well, as the oversight to also extend it to
source notes has previously caused bugs and because record selector ticking is
coverage-specific.
Fixes #17155, #15932.
- - - - -
836ec50a by Simon Peyton Jones at 2026-10-13T18:12:54-04:00
Refactor fundeps again
This MR fixes #27828; there was a bad scoping error in `trim_qtvs`.
The main changes are
* Refactor `trim_qtvs` completely to eliminate the bug.
* Remove a redundant `apartnessCheck` from `mkTopOpenFamEqFDs`.
* Lots of improvements to the Notes in FunDeps.hs
I also did a couple of pure refactors:
* I realised that we were carefully caching `cab_incomps` in each
`CoAxBranch`, to make it more efficient to reduce a type family application,
but we were not doing the same thing when computing relevance for functional
dependencies; see Note [Relevance] in GHC.Tc.Solver.FunDeps. So I added
`cab_overlaps`, which is now used in `noEarlierMatch`.
* Use a proper data types, `AmIUnifying` and `OuterKindsFlag`, for two
previously-Boolean arguments to `tc_unify_tys`. This is a pure refactor.
- - - - -
889ef371 by Simon Peyton Jones at 2026-10-13T18:13:36-04:00
Refactor and simplify solver's unification code
Ticket #27844 showed that GHC's constraint solver could miss an
occurs check, and thereby build an infinite type.
This patch significantly simplifes the code in
GHC.Tc.Solver.Equality.canEqCanLHSFinish_try_unification
GHC.Tc.Solver.Equality.canEqCanLHSFinish_no_unification
It is now significantly simpler, and requires much less subtle
reasoning to understand.
Main changes
* If `canEqCanLHSFinish_try_unification` fails to unify, it now /always/ calls
`canEqCanLHSFinish_no_unification` rather than trying to finish the job itself.
* `GHC.Tc.Solver.Monad.checkTypeEq` is moved from Monad into Equality, and renamed
to `GHC.Tc.Solver.Equality.checkTypeEqNoUnification`.
* `canEqCanLHSFinish_no_unification` calls `checkTypeEqNoUnification` to test
the invariants for an inert equality. Before this MR there was a special case for
`do_not_prevent_rewriting`, but that has gone; instead it's just a consequence of
the flags passed to `checkTyEqRhs`, documented in the `PuOK` case of
`canEqCanLHSFinish_no_unification`.
* There is only one bit of "swap back" code, in `finish_no_unify` in
`canEqCanLHSFinish_try_unification. Previously this code was duplicated.
* `kickOutAfterFillingCoercionHole` should account for equalities with a
TyFamLHS. See (KOC5) in Note [Kick out after filling a coercion hole]
* No need to gather coercion holes in the `PuOK` case of `canEqCanLHSFinish_no_unification`.
See documentation with that code.
- - - - -
f9193e53 by Simon Peyton Jones at 2026-10-13T18:13:37-04:00
One line fix to fallout from
...#27731, !16564, simplifying Tc.Errors machinery
There was an over-eager assert!
- - - - -
cdd56b7a by Florian Ragwitz at 2026-10-13T18:14:19-04:00
Fix several sphinx errors and warnings from rendering the release notes
The extension references which are removed here are for extension which were
already previously undocumented, so just removing them seems fine for now.
- - - - -
4f00da25 by Florian Ragwitz at 2026-10-13T18:14:19-04:00
Link to QualifiedStrings documentation
- - - - -
97adaf89 by Simon Peyton Jones at 2026-10-14T00:07:27+01:00
Line up simpleUnifyCheck and check_ty_eq_rhs
Even after #26543 was allegedly fixed, the original repo case in the
Description continued to fail. The reason was that the QuickLook
unifier, `qlUnify`, used `simpleUnifyCheck` for checking unification
invariants; and `simpleUnifyCheck` conservatively rejected any RHS
with a coercion hole in it. The upshot was that QuickLook was not
as clever as it should be, wrongly failing to do an impredicative
instantiation.
Interestingly `check_ty_eq_rhs`, which does the same job during
constraint solving, was more liberal: it just looked at the free vars
of the coercion, and allowed coercion holes.
This MR lines them up, adding some careful notes. See
Note [simpleUnifyCheck]
Note [Occurs check and coercions]
Note [Unification preconditions] esp (COERCIONS)
Things are better than before, but I am still uncomfortable about the
possibilty that a hole might be filled with a coercion that mentions
the LHS type variable; for now I have left this discomfort documented
in Note [Occurs check and coercions].
Main changes
* `qlUnify` now only unifies /instantiation variables/ not regular unification
variables. This makes QuickLook more predictable. See (UQL6) in
Note [QuickLook unification].
* `qlUnify` no longer needs to call `simpleUnifyCheck`, so we can get rid of
`UC_QuickLook` and its code in `simpleUnifyCheck`.
* I found I could get rid of `mkOccFolders` in favour of `anyFreeVarsOfType`.
Hooray.
* Improve documentation of CycleBreakerTv, and rename it to GivenCycleBreakerTv
because they are only uesd for Givens!
* I accepted a 9% worsening in compile time allocation on T5030
because the newly-consistent story triggered #27934.
Other changes
* I refactored `atvFolder` so that it pairs the "interesting-var" function
with the in-scope set, to avoid building a closure with a free variable.
Now we get nice tight loops for `anyFreeVarsOfType` and friends.
See Note [Any-free-var folder].
Metric Increase:
T5030
- - - - -
5f7b3047 by Simon Peyton Jones at 2026-10-14T00:07:27+01:00
Fix order-dependence in QuickLook
Ticket #27917 pointed out that QuickLook was order-dependent
-- very bad!
The solution is in `qlUnify`: spot when we are unifying a type with a
definite monotype, and then monomorphise any free instantiation
variables of that type.
See (UQL8) and (UQL9) in Note [QuickLook unification].
- - - - -
c391c70c by Simon Peyton Jones at 2026-10-14T00:07:28+01:00
Add some comments about RuntimeUnk
This commit just adds comments explaining why we don't need to worry about
RuntimeUnkTv in the constraint solver.
It also tightens up docmentation of earlier (overlapping) commits in
this MR.
- - - - -
7df3ba2f by Andrea Vezzosi at 2026-10-14T06:15:48-04:00
add runGhcWithSignalHandlers and remove handling from runGhc[T]
it only ever makes sense to call `withSignalHandlers` from `main`, otherwise
signals can be too easily swallowed without notification to the rest of your
process.
This commit takes withSignalHandlers out of `runGhc/runGhcT` and provides
`runGhcWithSignalHandlers` for the old behaviour.
- - - - -
3a72b8a2 by Hannes Siebenhandl at 2026-10-14T13:48:32-04:00
Fix #27836, normalise unit database path in ExternalUnitDatabases
Add a regression test, proofing that all variations:
- local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf/
are parsed only once.
- - - - -
8ddbc6f9 by Florian Ragwitz at 2026-10-14T13:49:28-04:00
Remove obsolete HPC types
Fixes #27946.
- - - - -
29497219 by Vladislav Zavialov at 2026-10-14T21:16:56+02:00
Curried contexts in prefix GADT constructors (#27424)
Prefix GADT constructor declarations now accept multiple consecutive
contexts, equivalent to a single conjoined context:
data G a where
MkCurried :: C a => (D a, E a) => G a
MkConjoined :: (C a, D a, E a) => G a
This is a step towards GHC Proposal #402 "Stable GADT constructor syntax".
To represent multiple contexts, the `con_mb_cxt` field of `ConDeclGADT` has
been replaced by `con_cxts`, which stores a list instead of a Maybe:
- con_mb_cxt :: Maybe (LHsContext pass)
+ con_cxts :: [LHsContext pass]
The rest of this patch follows from this change.
Note that in ConDeclH98, the optional context is still stored as a Maybe.
To accommodate this difference, a few helper functions were generalised over
a Foldable container `t`:
hsConDeclTheta :: Foldable t => t (LHsContext ...) -> [LHsType ...]
pprLHsContext :: (Foldable t, ...) => t (LHsContext ...) -> SDoc
repContexts :: Foldable t => t (LHsContext GhcRn) -> MetaM (Core (M TH.Cxt))
tcHsContext :: Foldable t => t (LHsContext GhcRn) -> TcM [PredType]
In practice, the instantiations of `t` are either `Maybe` or `[]`.
Record-style GADT constructors continue to accept at most one context.
`splitLHsGadtTy` accounts for this by splitting off only the first context
if it detects record syntax, leaving the offending part of the type in the
body for the renamer to reject later on.
Test cases: T12087a T27424a T27424b T27424c GadtConSigs_th_dump1
- - - - -
450 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/hello.hs
- + changelog.d/24450
- + changelog.d/26610
- changelog.d/26616
- + changelog.d/26761
- + changelog.d/27641
- + changelog.d/27845
- + changelog.d/T23785
- + changelog.d/T26543
- changelog.d/T27329
- changelog.d/T27455
- + changelog.d/T27545
- + changelog.d/T27731
- + changelog.d/T27828
- + changelog.d/T27830-rts-flag-bounds
- + changelog.d/T27844
- + changelog.d/T27916
- + changelog.d/T4162
- changelog.d/allow-gadt-prefix-con-parens
- changelog.d/boxing-family
- + changelog.d/clc-341-strict-mutable-data-types
- + changelog.d/fix-cross-ghc-info-unit-id
- changelog.d/fix-parallel-gc-selector-race-27477
- + changelog.d/gadt-curried-contexts-27424
- + changelog.d/hadrian-persist-flavour
- + changelog.d/hpc-classinsts
- + changelog.d/hpc-cleanup
- changelog.d/semaphore-v2
- changelog.d/tcplugin_init.md
- changelog.d/unit-index
- compiler/GHC.hs
- compiler/GHC/Builtin/Modules.hs
- compiler/GHC/Builtin/WiredIn/Ids.hs
- compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Builtin/WiredIn/Types/Box.hs
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Show.hs
- compiler/GHC/Cmm/GenericOpt.hs
- compiler/GHC/Cmm/UniqueRenamer.hs
- compiler/GHC/CmmToAsm/Dwarf/Types.hs
- compiler/GHC/CmmToAsm/Monad.hs
- compiler/GHC/CmmToAsm/Reg/Graph/Spill.hs
- compiler/GHC/CmmToAsm/Reg/Graph/SpillClean.hs
- compiler/GHC/CmmToAsm/Reg/Graph/SpillCost.hs
- compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs
- compiler/GHC/CmmToAsm/Reg/Linear/State.hs
- compiler/GHC/CmmToAsm/Reg/Linear/Stats.hs
- compiler/GHC/CmmToAsm/Reg/Liveness.hs
- compiler/GHC/CmmToAsm/Wasm/Asm.hs
- compiler/GHC/CmmToAsm/Wasm/Types.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion.hs-boot
- compiler/GHC/Core/Coercion/Axiom.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Make.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/CallerCC.hs
- compiler/GHC/Core/Opt/CallerCC/Types.hs
- compiler/GHC/Core/Opt/Exitify.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Reduction.hs
- compiler/GHC/Core/Seq.hs
- compiler/GHC/Core/TyCo/Compare.hs
- compiler/GHC/Core/TyCo/FVs.hs
- + compiler/GHC/Core/TyCo/Make.hs
- + compiler/GHC/Core/TyCo/Make.hs-boot
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCo/Rep.hs-boot
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Type.hs-boot
- compiler/GHC/Core/Unify.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToIface.hs-boot
- compiler/GHC/CoreToStg.hs
- compiler/GHC/Data/OsPath.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Main/Compile.hs
- compiler/GHC/Driver/Pipeline.hs-boot
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Hs/Lit.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Match/Literal.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Errors/Types.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Ext/Debug.hs
- compiler/GHC/Iface/Ext/Types.hs
- compiler/GHC/Iface/Ext/Utils.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Iface/Type.hs-boot
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Parser/String.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Unbound.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/Stg/BcPrep.hs
- compiler/GHC/Stg/Debug.hs
- compiler/GHC/Stg/EnforceEpt/Rewrite.hs
- compiler/GHC/Stg/EnforceEpt/TagSig.hs
- compiler/GHC/Stg/Subst.hs
- compiler/GHC/StgToJS/ExprCtx.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Deriv/Functor.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/ErrCtxt.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Env.hs
- compiler/GHC/Tc/Zonk/Monad.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Arity.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Cpr.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Name/Env.hs
- compiler/GHC/Types/Name/Occurrence.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/DSM.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Unique/Map.hs
- compiler/GHC/Types/Unique/Set.hs
- compiler/GHC/Types/Unique/Supply.hs
- compiler/GHC/Types/UnresolvedImport.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Types/Var.hs-boot
- compiler/GHC/Types/Var/FV.hs
- compiler/GHC/Types/Var/Set.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/External/Database.hs
- compiler/GHC/Unit/External/Wired.hs
- compiler/GHC/Unit/Home.hs
- compiler/GHC/Unit/Module.hs
- compiler/GHC/Unit/Module/Env.hs
- + compiler/GHC/Unit/Module/Name.hs
- compiler/GHC/Unit/Parser.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Unit/Types.hs
- compiler/GHC/Unit/Types.hs-boot
- compiler/GHC/Utils/Binary.hs
- + compiler/GHC/Utils/Monad/StrictIdentity.hs
- + compiler/GHC/Utils/Monad/StrictReader.hs
- compiler/GHC/Utils/Monad/State/Strict.hs → compiler/GHC/Utils/Monad/StrictState.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/GHC/Utils/Panic.hs
- compiler/Language/Haskell/Syntax.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Expr.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- compiler/Language/Haskell/Syntax/Lit.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- compiler/Language/Haskell/Syntax/Specificity.hs
- compiler/Language/Haskell/Syntax/Text.hs
- compiler/Language/Haskell/Syntax/Type.hs
- compiler/ghc.cabal.in
- distrib/configure.ac.in
- docs/users_guide/exts/gadt_syntax.rst
- docs/users_guide/exts/literals.rst
- docs/users_guide/runtime_control.rst
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Info.hs
- ghc/Main.hs
- hadrian/bindist/Makefile
- hadrian/bindist/config.mk.in
- hadrian/doc/flavours.md
- hadrian/ghci-multi-cabal.in
- hadrian/src/Rules.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Settings.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Control/Concurrent/Chan.hs
- + libraries/base/src/Control/Concurrent/Chan/Strict.hs
- libraries/base/src/Control/Concurrent/MVar.hs
- + libraries/base/src/Control/Concurrent/MVar/Strict.hs
- libraries/base/src/Data/IORef.hs
- + libraries/base/src/Data/IORef/Strict.hs
- libraries/containers
- libraries/ghc-internal/src/GHC/Internal/Bits.hs
- linters/lint-codes/LintCodes/Static.hs
- m4/subst_tooldir.m4
- rts/RtsFlags.c
- rts/RtsStartup.c
- rts/include/rts/Flags.h
- rts/include/rts/storage/GC.h
- rts/include/stg/Prim.h
- rts/prim/bitrev.c
- rts/prim/bswap.c
- rts/sm/GC.c
- rts/sm/Storage.c
- testsuite/driver/junit.py
- testsuite/driver/runtests.py
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- + testsuite/tests/backpack/should_compile/T27835.bkp
- + testsuite/tests/backpack/should_compile/T27835.stderr
- testsuite/tests/backpack/should_compile/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/default/default-fail05.stderr
- + testsuite/tests/dmdanal/should_run/T27845.hs
- + testsuite/tests/dmdanal/should_run/T27845.stdout
- + testsuite/tests/dmdanal/should_run/T27845_Lib.hs
- + testsuite/tests/dmdanal/should_run/T27845b.hs
- + testsuite/tests/dmdanal/should_run/T27845b.stdout
- + testsuite/tests/dmdanal/should_run/T27845b_Lib.hs
- testsuite/tests/dmdanal/should_run/all.T
- + testsuite/tests/driver/T27836/A.hs
- + testsuite/tests/driver/T27836/B.hs
- + testsuite/tests/driver/T27836/C.hs
- + testsuite/tests/driver/T27836/Makefile
- + testsuite/tests/driver/T27836/T27836.stdout
- + testsuite/tests/driver/T27836/all.T
- + testsuite/tests/driver/T27836/unitA
- + testsuite/tests/driver/T27836/unitB
- + testsuite/tests/driver/T27836/unitC
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/Makefile
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stderr
- testsuite/tests/driver/multipleHomeUnits/mhu-closure/mhu-closure.stdout
- testsuite/tests/gadt/T12087.hs
- − testsuite/tests/gadt/T12087.stderr
- + testsuite/tests/gadt/T12087a.hs
- + testsuite/tests/gadt/T12087b.stderr
- + testsuite/tests/gadt/T27424a.hs
- + testsuite/tests/gadt/T27424b.hs
- + testsuite/tests/gadt/T27424b.stderr
- testsuite/tests/gadt/all.T
- + testsuite/tests/ghc-api/T4162.hs
- + testsuite/tests/ghc-api/T4162.stdout
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghc-api/downsweep/IncrementalDownsweep.hs
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/Test20239.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/ghci.debugger/scripts/T14628.stderr
- + testsuite/tests/ghci/prog-mhu008/Makefile
- + testsuite/tests/ghci/prog-mhu008/a/M.hs
- + testsuite/tests/ghci/prog-mhu008/all.T
- + testsuite/tests/ghci/prog-mhu008/b/M.hs
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.script
- + testsuite/tests/ghci/prog-mhu008/prog-mhu008.stdout
- + testsuite/tests/ghci/prog-mhu008/unitA
- + testsuite/tests/ghci/prog-mhu008/unitB
- testsuite/tests/ghci/prog020/ghci.prog020a.stderr
- testsuite/tests/ghci/prog020/ghci.prog020b.stderr
- testsuite/tests/ghci/prog021/prog021a.stderr
- testsuite/tests/ghci/prog021/prog021b.stderr
- testsuite/tests/ghci/prog022/ghci.prog022a.stderr
- testsuite/tests/ghci/prog022/ghci.prog022b.stderr
- testsuite/tests/ghci/prog022/ghci.prog022c.stderr
- testsuite/tests/ghci/prog022/ghci.prog022d.stderr
- testsuite/tests/ghci/prog022/ghci.prog022e.stderr
- testsuite/tests/ghci/prog022/ghci.prog022f.stderr
- testsuite/tests/ghci/scripts/Defer02.stderr
- + testsuite/tests/ghci/scripts/T27641.script
- + testsuite/tests/ghci/scripts/T27641.stderr
- + testsuite/tests/ghci/scripts/T27641.stdout
- + testsuite/tests/ghci/scripts/T27834.hs
- + testsuite/tests/ghci/scripts/T27834.script
- + testsuite/tests/ghci/scripts/T27834.stdout
- testsuite/tests/ghci/scripts/all.T
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr
- testsuite/tests/hiefile/should_run/T24544.hs
- + testsuite/tests/hpc/instmeths/instmeths.hs
- + testsuite/tests/hpc/instmeths/instmeths.stdout
- + testsuite/tests/hpc/instmeths/test.T
- + testsuite/tests/impredicative/T27917.hs
- testsuite/tests/impredicative/all.T
- + testsuite/tests/indexed-types/should_compile/T27828.hs
- + testsuite/tests/indexed-types/should_compile/T27828a.hs
- + testsuite/tests/indexed-types/should_compile/T27828b.hs
- testsuite/tests/indexed-types/should_compile/all.T
- testsuite/tests/indexed-types/should_fail/T1897b.stderr
- testsuite/tests/indexed-types/should_fail/T9662.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/module/mod130.stderr
- testsuite/tests/module/mod185.stderr
- + testsuite/tests/numeric/should_run/T27545.hs
- + testsuite/tests/numeric/should_run/T27545.stdout
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/overloadedstrings/should_fail/T25926.stderr
- testsuite/tests/overloadedstrings/should_fail/T27124.stderr
- testsuite/tests/package/T4806a.stderr
- testsuite/tests/package/all.T
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20718b.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/T23315/T23315.stderr
- testsuite/tests/patsyn/should_fail/records-nofieldselectors.stderr
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/plugins/T26761.hs
- + testsuite/tests/plugins/T26761.stderr
- + testsuite/tests/plugins/T26761Plugin.hs
- + testsuite/tests/plugins/T26761a.hs
- testsuite/tests/plugins/all.T
- + testsuite/tests/primops/should_run/T27299.hs
- + testsuite/tests/primops/should_run/T27299.stdout
- testsuite/tests/primops/should_run/all.T
- testsuite/tests/printer/AnnotationNoListTuplePuns.stdout
- testsuite/tests/printer/Makefile
- testsuite/tests/printer/T17697.stderr
- testsuite/tests/printer/T18791.stderr
- + testsuite/tests/printer/T27424c.hs
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- testsuite/tests/printer/all.T
- testsuite/tests/profiling/should_run/caller-cc/CallerCcParser.hs
- testsuite/tests/rename/should_fail/T15607.stderr
- testsuite/tests/rename/should_fail/T19843b.stderr
- + testsuite/tests/rts/T24450.hs
- + testsuite/tests/rts/T24450.stderr
- testsuite/tests/rts/all.T
- testsuite/tests/rts/rtsflags001.stderr-ws-32
- testsuite/tests/rts/rtsflags001.stderr-ws-64
- testsuite/tests/safeHaskell/ghci/p4.stderr
- testsuite/tests/safeHaskell/ghci/p6.stderr
- testsuite/tests/simplCore/should_compile/T22375.stderr
- testsuite/tests/simplCore/should_compile/T22375DataFamily.stderr
- testsuite/tests/simplCore/should_compile/T22611.hs
- testsuite/tests/simplCore/should_compile/T22611.stderr
- + testsuite/tests/simplCore/should_compile/T22611a.hs
- + testsuite/tests/simplCore/should_compile/T7803.hs
- + testsuite/tests/simplCore/should_compile/T7803.stderr
- + testsuite/tests/simplCore/should_compile/T7803a.hs
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/th/GadtConSigs_th_dump1.hs
- testsuite/tests/th/GadtConSigs_th_dump1.stderr
- testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs
- testsuite/tests/typecheck/should_compile/T11254.stderr
- testsuite/tests/typecheck/should_compile/T15370.stderr
- + testsuite/tests/typecheck/should_compile/T26543_orig.hs
- + testsuite/tests/typecheck/should_compile/T27916.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/ClassOperator.stderr
- testsuite/tests/typecheck/should_fail/DoExpansion2.stderr
- testsuite/tests/typecheck/should_fail/DoExpansion3.stderr
- testsuite/tests/typecheck/should_fail/FunDepOrigin1b.hs
- testsuite/tests/typecheck/should_fail/T12785b.stderr
- testsuite/tests/typecheck/should_fail/T18851.stderr
- + testsuite/tests/typecheck/should_fail/T18851e.hs
- + testsuite/tests/typecheck/should_fail/T18851e.stderr
- + testsuite/tests/typecheck/should_fail/T18851f.hs
- + testsuite/tests/typecheck/should_fail/T18851f.stderr
- testsuite/tests/typecheck/should_fail/T22707.stderr
- testsuite/tests/typecheck/should_fail/T22940.stderr
- + testsuite/tests/typecheck/should_fail/T26543a.hs
- + testsuite/tests/typecheck/should_fail/T26543a.stderr
- testsuite/tests/typecheck/should_fail/T26823.stderr
- + testsuite/tests/typecheck/should_fail/T27731.hs
- + testsuite/tests/typecheck/should_fail/T27731.stderr
- + testsuite/tests/typecheck/should_fail/T27844.hs
- + testsuite/tests/typecheck/should_fail/T27844.stderr
- testsuite/tests/typecheck/should_fail/T5691.stderr
- testsuite/tests/typecheck/should_fail/T7437.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_fail/mc24.stderr
- testsuite/tests/typecheck/should_fail/tcfail019.stderr
- testsuite/tests/typecheck/should_fail/tcfail189.stderr
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/check-ppr/Main.hs
- utils/count-deps/Main.hs
- utils/dump-decls/Main.hs
- utils/haddock/haddock-api/src/Haddock.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Renderer.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.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/test/Haddock/Backends/Hyperlinker/ParserSpec.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/bb2c9f3555bfd5d3ce16eafecd2132…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/bb2c9f3555bfd5d3ce16eafecd2132…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/rafl/meaningful-main-return] 20 commits: Simplify the error-suppression mechanism in GHC.Tc.Errors
by Florian Ragwitz (@rafl) 14 Oct '26
by Florian Ragwitz (@rafl) 14 Oct '26
14 Oct '26
Florian Ragwitz pushed to branch wip/rafl/meaningful-main-return at Glasgow Haskell Compiler / GHC
Commits:
41e80f41 by Simon Peyton Jones at 2026-10-11T14:38:51-04:00
Simplify the error-suppression mechanism in GHC.Tc.Errors
In `GHC.Tc.Errors.reportWanteds` we suppress some errors in favour of
others. But the mechanism had grown crufty, and #27331 exposed a bug.
This MR makes it simpler and more uniform, by doing everything via
the `ei_suppress` field of the ErrorItem.
Claude then found another closely-related bug (see the review linked
on !16564). That bug is immortalised in new test T18851d.
I'm still not happy with `ignoreConstraint` but we can worry about
that another day; I have not touched it.
Main changes
* Instead of /predicting/ when an error will be reported, we set
`cec_error_reported` when an error is /actually/ reported. (I renamed
it from `cec_suppress` to reflect this change.)
Now errors are suppressed only when a preceding error has actually been
reported. Simpler and more robust.
See `Note [cec_error_reported: suppressing less-serious errors]`
The big changes are in `reportWanteds` which looks very different.
* New `Note [ei_suppress: suppressing confusing errors]` describes the
(quite separate) `ei_suppress` mechanism for suppressing confusing
errors, mainly arising from non-empty rewriter sets
* In `tryTypeClassDefaulting`, instead of switching off type-class defaulting
if there is an insoluble /anywhere/, we just switch it off locally when
we find an insoluble sub-tree. See Note [When to do type-class defaulting]
and (W5) in Note [ApproximateWC]
* Greatly simplify `insolubleWantedCt`.
* I made type-class-defaulting be a bit more eager, only switched off when
a peer or ancestor (but not child) constraint is insoluble. See
Note [When to do type-class defaulting].
Small refactorings
* Rename `askNoErrs` to `askErrsFound` and flip its polarity
* The code for "check if ei_suppress is true of all items" code is
moved to `mkErrorItems` rather than in the large `reportWanteds`.
* Code for `has_gadt_match` moves to `mkGivenErrorReporter`, rather than
polluting the large `reportWanteds`.
* Many tests with `-fdefer-type-errors` get more warnings, especially
about ambiguous (Num a) constraints. This is by-design: see
Note [Always warn with -fdefer-type-errors]. Previously GHC was not
honouring this Note but now it is, hence the extra errors.
- - - - -
f217fc31 by Cheng Shao at 2026-10-11T14:39:33-04:00
compiler: ensure cross ghc --info output target unit ids
Previously, for cross ghcs, the base/ghc/ghc-internal unit ids in
--info output do not match the target unit ids reported by ghc-pkg,
breaking cross ghc release builds with hash-unit-ids when being used
with cabal 3.18. This patch fixes it by making --info output target
unit ids. Fixes #27919.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
d07a5176 by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Remove the Eq and Ord instances for ForAllTyFlag
In Note [Comparing visibility] in GHC.Core.TyCo.Compare we read that
"we always compare ForAllTyFlags with `eqForAllVis` or `cmpForAllVis`"
But alas there was an Eq and Ord instance for ForAllTyFlag, which made it
impossible to check this claim. So I made these changes:
* Move the definition of ForAllTyFlag and its related functions from
L.H.S.Specificity (where it did not belong, since L.H.S didn't use it)
into GHC.Types.Var.
* Remove the Eq and Ord instances for ForAllTyFlag
* Deal with the fallout, by using `eqForAllVis` or related functions.
* In interface files we use IfaceType as a key for a de-deduplication map
See Note [Deduplication during iface binary serialisation]
in GHC.Iface.Binary. For this we need /exact/ comparison, so we use a
newtype wrapper for IfaceForAllTyFlag, and give use `cmpForAllTyFlagExactly`
to implement its Ord instance. Tiresome but easy.
* Rename `toIfaceForAllBndrs` to `toIfaceForAllTyBndrs`
- - - - -
ea5c054d by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Refactor type and coercion substitution
This MR refactors type and coercion substitution so that they use
TyCoMapper, rather than hand-rolled code. Fundamentally it's a simple
idea, but I had to do quite a bit of refactoring to make it fly.
I got Claude to help me this this refactoring, but I paid careful
attention to every line of code.
Main changes:
* New module GHC.Core.TyCo.Make which defines TyCoMapper, and a bunch of other
simple "smart constructors" for types and coercions. See
GHC.Core.TyCo.Rep Note [The Type-related module hierarchy], esp (TRM1)
* The new TyCoMapper has new fields `tcm_tcapp_ty` and `tcm_tcapp_co` to handle
type-constructor applications. These replace `tcm_tycon`.
* Rewrite GHC.Core.TyCo.Subst to use TyCoMapper
* Rewrite GHC.Core.Type.expandTypeSynonyms to use TyCoMapper.
* Implement `seqType` and `seqCo` with TyCoFolder. To to this I had to add
a `tcf_lit` field to TyCoFolder.
* A new module GHC.Utils.StrictIdentity to define a strict identity monad,
which itself is used for
substTyCoMapper :: TyCoMapper Subst StrictIdentity
* I removed an apparently-unused instance for Binary Levity
Refactoring `seq` functions
* In GHC.Core.Seq, redefine `seqOneShot`, `seqRuleInfo`, and friends to return
`SeqResult`, a new type defined in GHC.Types.Baseic, rather than `()`. We
can define a Monoid instance for `SeqResult` that does the right thing.
* This has knock-on effects across the compiler.
- - - - -
34165e23 by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Refactor TyCoMapper to take a single monad; add StrictReaderT
TyCoMapper used to be parameterised over both an environment and a
monad, with fields like
tcm_tyvar :: env -> TyVar -> m Type
Now it is parameterised over just the monad:
tcm_tyvar :: TyVar -> m Type
If the mapping needs an environment, `m` is a reader monad over that
environment. Many uses (e.g. zonkTcTypeMapper, swizzleMapper) need no
environment at all, and used to pass a dummy (). The binder field
becomes
tcm_tycobinder :: forall r. TyCoVar -> ForAllTyFlag
-> (TyCoVar -> m r) -> m r
and runs the continuation in the extended environment. mapTyCoX is gone;
only mapTyCo remains.
To make this efficient, the reader monad must use the one-shot trick and
be strict in the environment. So:
* New module GHC.Utils.Monad.StrictReader defines
newtype StrictReaderT r m a
with hand-written instances. The builder of the pattern synonym
`StrictReaderT` is a smart constructor that adds both `oneShot` and a
bang on the environment, so every StrictReaderT computation is strict
in the environment. See Note [Instances for StrictReaderT].
* ZonkT becomes type ZonkT = StrictReaderT ZonkEnv
ZonkM becomes type ZonkM = StrictReaderT ZonkGblEnv IO
replacing their own hand-written instances.
* Substitution uses
type SubstM = StrictReaderT Subst StrictIdentity
substTyCoMapper :: TyCoMapper SubstM
and similarly expandTypeSynonymMapper.
* zonk_tycomapper :: TyCoMapper (ZonkT TcM) is now much simpler.
* swizzleMapper uses StrictIdentity rather than Identity.
* Module renaming, so that the strict monads are all peers in GHC.Utils.Monad:
GHC.Utils.StrictIdentity ==> GHC.Utils.Monad.StrictIdentity
GHC.Utils.Monad.State.Strict ==> GHC.Utils.Monad.StrictState
alongside the new GHC.Utils.Monad.StrictReader.
Co-Authored-By: Claude Opus 5.5 <noreply(a)anthropic.com>
- - - - -
c0299e15 by Simon Jakobi at 2026-10-13T18:11:23-04:00
testsuite: Line-buffer the driver's stdout
Python block-buffers stdout when it is a pipe. This is the case for
example in CI. As a result there is often no indication of progress at
all until the run ends.
To fix this, we configure it explicitly to use line buffering instead.
stderr is reconfigured too, for consistency: Python line-buffers it by
default since 3.9.
The type-ignores are for mypy, which types these handles as TextIO — an
interface without reconfigure.
Fixes #12934.
Assisted-by: Claude Fable 5
- - - - -
9b5beaa2 by Florian Ragwitz at 2026-10-13T18:12:05-04:00
hpc: Improve coverage semantics for instance methods and instances
Users care about which of their explicitly written methods are or aren't
covered, not whether all of the inherited methods are covered as well. Those
should be covered where they are implemented.
We therefore skip generating top-level boxes for inherited methods which will
appear as uncovered with no clear indication as to why, and no way to fix other
than exercising code the user has not written.
Previously, top-level boxes for those inherited methods would use the instance
head as their source span. Now that those boxes are gone, we can use that
source span for another purpose:
We introduce a new top-level box for each class instance with its instance head
as the source span, and use that to indicate whether or not an instance has
been covered at all.
We do this by making any method of the instance, inherited/generated or
otherwise, tick the box for the instance head. Excluded from this are
methodless classes, which could never be covered using the current mechanism.
This could be improved upon further.
These changes apply to ticking for program coverage only, and don't affect
source notes. Additionally, we update the scope of record selector ticking to
be limited to program coverage as well, as the oversight to also extend it to
source notes has previously caused bugs and because record selector ticking is
coverage-specific.
Fixes #17155, #15932.
- - - - -
836ec50a by Simon Peyton Jones at 2026-10-13T18:12:54-04:00
Refactor fundeps again
This MR fixes #27828; there was a bad scoping error in `trim_qtvs`.
The main changes are
* Refactor `trim_qtvs` completely to eliminate the bug.
* Remove a redundant `apartnessCheck` from `mkTopOpenFamEqFDs`.
* Lots of improvements to the Notes in FunDeps.hs
I also did a couple of pure refactors:
* I realised that we were carefully caching `cab_incomps` in each
`CoAxBranch`, to make it more efficient to reduce a type family application,
but we were not doing the same thing when computing relevance for functional
dependencies; see Note [Relevance] in GHC.Tc.Solver.FunDeps. So I added
`cab_overlaps`, which is now used in `noEarlierMatch`.
* Use a proper data types, `AmIUnifying` and `OuterKindsFlag`, for two
previously-Boolean arguments to `tc_unify_tys`. This is a pure refactor.
- - - - -
889ef371 by Simon Peyton Jones at 2026-10-13T18:13:36-04:00
Refactor and simplify solver's unification code
Ticket #27844 showed that GHC's constraint solver could miss an
occurs check, and thereby build an infinite type.
This patch significantly simplifes the code in
GHC.Tc.Solver.Equality.canEqCanLHSFinish_try_unification
GHC.Tc.Solver.Equality.canEqCanLHSFinish_no_unification
It is now significantly simpler, and requires much less subtle
reasoning to understand.
Main changes
* If `canEqCanLHSFinish_try_unification` fails to unify, it now /always/ calls
`canEqCanLHSFinish_no_unification` rather than trying to finish the job itself.
* `GHC.Tc.Solver.Monad.checkTypeEq` is moved from Monad into Equality, and renamed
to `GHC.Tc.Solver.Equality.checkTypeEqNoUnification`.
* `canEqCanLHSFinish_no_unification` calls `checkTypeEqNoUnification` to test
the invariants for an inert equality. Before this MR there was a special case for
`do_not_prevent_rewriting`, but that has gone; instead it's just a consequence of
the flags passed to `checkTyEqRhs`, documented in the `PuOK` case of
`canEqCanLHSFinish_no_unification`.
* There is only one bit of "swap back" code, in `finish_no_unify` in
`canEqCanLHSFinish_try_unification. Previously this code was duplicated.
* `kickOutAfterFillingCoercionHole` should account for equalities with a
TyFamLHS. See (KOC5) in Note [Kick out after filling a coercion hole]
* No need to gather coercion holes in the `PuOK` case of `canEqCanLHSFinish_no_unification`.
See documentation with that code.
- - - - -
f9193e53 by Simon Peyton Jones at 2026-10-13T18:13:37-04:00
One line fix to fallout from
...#27731, !16564, simplifying Tc.Errors machinery
There was an over-eager assert!
- - - - -
cdd56b7a by Florian Ragwitz at 2026-10-13T18:14:19-04:00
Fix several sphinx errors and warnings from rendering the release notes
The extension references which are removed here are for extension which were
already previously undocumented, so just removing them seems fine for now.
- - - - -
4f00da25 by Florian Ragwitz at 2026-10-13T18:14:19-04:00
Link to QualifiedStrings documentation
- - - - -
97adaf89 by Simon Peyton Jones at 2026-10-14T00:07:27+01:00
Line up simpleUnifyCheck and check_ty_eq_rhs
Even after #26543 was allegedly fixed, the original repo case in the
Description continued to fail. The reason was that the QuickLook
unifier, `qlUnify`, used `simpleUnifyCheck` for checking unification
invariants; and `simpleUnifyCheck` conservatively rejected any RHS
with a coercion hole in it. The upshot was that QuickLook was not
as clever as it should be, wrongly failing to do an impredicative
instantiation.
Interestingly `check_ty_eq_rhs`, which does the same job during
constraint solving, was more liberal: it just looked at the free vars
of the coercion, and allowed coercion holes.
This MR lines them up, adding some careful notes. See
Note [simpleUnifyCheck]
Note [Occurs check and coercions]
Note [Unification preconditions] esp (COERCIONS)
Things are better than before, but I am still uncomfortable about the
possibilty that a hole might be filled with a coercion that mentions
the LHS type variable; for now I have left this discomfort documented
in Note [Occurs check and coercions].
Main changes
* `qlUnify` now only unifies /instantiation variables/ not regular unification
variables. This makes QuickLook more predictable. See (UQL6) in
Note [QuickLook unification].
* `qlUnify` no longer needs to call `simpleUnifyCheck`, so we can get rid of
`UC_QuickLook` and its code in `simpleUnifyCheck`.
* I found I could get rid of `mkOccFolders` in favour of `anyFreeVarsOfType`.
Hooray.
* Improve documentation of CycleBreakerTv, and rename it to GivenCycleBreakerTv
because they are only uesd for Givens!
* I accepted a 9% worsening in compile time allocation on T5030
because the newly-consistent story triggered #27934.
Other changes
* I refactored `atvFolder` so that it pairs the "interesting-var" function
with the in-scope set, to avoid building a closure with a free variable.
Now we get nice tight loops for `anyFreeVarsOfType` and friends.
See Note [Any-free-var folder].
Metric Increase:
T5030
- - - - -
5f7b3047 by Simon Peyton Jones at 2026-10-14T00:07:27+01:00
Fix order-dependence in QuickLook
Ticket #27917 pointed out that QuickLook was order-dependent
-- very bad!
The solution is in `qlUnify`: spot when we are unifying a type with a
definite monotype, and then monomorphise any free instantiation
variables of that type.
See (UQL8) and (UQL9) in Note [QuickLook unification].
- - - - -
c391c70c by Simon Peyton Jones at 2026-10-14T00:07:28+01:00
Add some comments about RuntimeUnk
This commit just adds comments explaining why we don't need to worry about
RuntimeUnkTv in the constraint solver.
It also tightens up docmentation of earlier (overlapping) commits in
this MR.
- - - - -
7df3ba2f by Andrea Vezzosi at 2026-10-14T06:15:48-04:00
add runGhcWithSignalHandlers and remove handling from runGhc[T]
it only ever makes sense to call `withSignalHandlers` from `main`, otherwise
signals can be too easily swallowed without notification to the rest of your
process.
This commit takes withSignalHandlers out of `runGhc/runGhcT` and provides
`runGhcWithSignalHandlers` for the old behaviour.
- - - - -
3a72b8a2 by Hannes Siebenhandl at 2026-10-14T13:48:32-04:00
Fix #27836, normalise unit database path in ExternalUnitDatabases
Add a regression test, proofing that all variations:
- local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf/
are parsed only once.
- - - - -
8ddbc6f9 by Florian Ragwitz at 2026-10-14T13:49:28-04:00
Remove obsolete HPC types
Fixes #27946.
- - - - -
a996c2cf by Florian Ragwitz at 2026-10-14T11:57:24-07:00
Move exitWith into GHC.IO.Exception
This is low enough within the hierarchy of base such that it can be imported
into GHC.Essentials.
The implementation of exitWith is slightly changed to avoid having to import
Data.Bool, which would lead to a dependency cycle.
We chose to keep it in base rather than moving it up all the way to
GHC.Internal.IO.Exception to allow a reinstallable base to change it
independently of GHC.
With this, we can now have a known occurrence for GHC to reference in order to
implement GHC proposal #631 (#24848).
- - - - -
92ece0b1 by Florian Ragwitz at 2026-10-14T11:57:25-07:00
Implement MeaningfulMainReturn
As per ghc-proposal#631, with one small adjustment explained in the comments.
Fixes #24848.
- - - - -
272 changed files:
- .gitlab/hello.hs
- changelog.d/26616
- + changelog.d/MeaningfulMainReturn
- + changelog.d/T26543
- changelog.d/T27329
- + changelog.d/T27731
- + changelog.d/T27828
- + changelog.d/T27844
- + changelog.d/T4162
- changelog.d/boxing-family
- + changelog.d/fix-cross-ghc-info-unit-id
- + changelog.d/hpc-classinsts
- + changelog.d/hpc-cleanup
- changelog.d/tcplugin_init.md
- changelog.d/unit-index
- compiler/GHC.hs
- compiler/GHC/Builtin/KnownOccs.hs
- compiler/GHC/Builtin/WiredIn/Ids.hs
- compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Builtin/WiredIn/Types/Box.hs
- compiler/GHC/Cmm/GenericOpt.hs
- compiler/GHC/Cmm/UniqueRenamer.hs
- compiler/GHC/CmmToAsm/Dwarf/Types.hs
- compiler/GHC/CmmToAsm/Monad.hs
- compiler/GHC/CmmToAsm/Reg/Graph/Spill.hs
- compiler/GHC/CmmToAsm/Reg/Graph/SpillClean.hs
- compiler/GHC/CmmToAsm/Reg/Graph/SpillCost.hs
- compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs
- compiler/GHC/CmmToAsm/Reg/Linear/State.hs
- compiler/GHC/CmmToAsm/Reg/Linear/Stats.hs
- compiler/GHC/CmmToAsm/Reg/Liveness.hs
- compiler/GHC/CmmToAsm/Wasm/Asm.hs
- compiler/GHC/CmmToAsm/Wasm/Types.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion.hs-boot
- compiler/GHC/Core/Coercion/Axiom.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/CallerCC.hs
- compiler/GHC/Core/Opt/Exitify.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Reduction.hs
- compiler/GHC/Core/Seq.hs
- compiler/GHC/Core/TyCo/Compare.hs
- compiler/GHC/Core/TyCo/FVs.hs
- + compiler/GHC/Core/TyCo/Make.hs
- + compiler/GHC/Core/TyCo/Make.hs-boot
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCo/Rep.hs-boot
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Type.hs-boot
- compiler/GHC/Core/Unify.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToIface.hs-boot
- compiler/GHC/CoreToStg.hs
- compiler/GHC/Data/OsPath.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main/Compile.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Types.hs
- compiler/GHC/Iface/Ext/Utils.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Iface/Type.hs-boot
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/Stg/BcPrep.hs
- compiler/GHC/Stg/Debug.hs
- compiler/GHC/Stg/EnforceEpt/Rewrite.hs
- compiler/GHC/Stg/EnforceEpt/TagSig.hs
- compiler/GHC/Stg/Subst.hs
- compiler/GHC/StgToJS/ExprCtx.hs
- compiler/GHC/Tc/Deriv/Functor.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Env.hs
- compiler/GHC/Tc/Zonk/Monad.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/Types/Arity.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Cpr.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Name/Env.hs
- compiler/GHC/Types/Name/Occurrence.hs
- compiler/GHC/Types/Unique/DSM.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Unique/Map.hs
- compiler/GHC/Types/Unique/Set.hs
- compiler/GHC/Types/Unique/Supply.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Types/Var.hs-boot
- compiler/GHC/Types/Var/FV.hs
- compiler/GHC/Types/Var/Set.hs
- compiler/GHC/Unit/External/Database.hs
- compiler/GHC/Utils/Binary.hs
- + compiler/GHC/Utils/Monad/StrictIdentity.hs
- + compiler/GHC/Utils/Monad/StrictReader.hs
- compiler/GHC/Utils/Monad/State/Strict.hs → compiler/GHC/Utils/Monad/StrictState.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/GHC/Utils/Panic.hs
- compiler/Language/Haskell/Syntax/Specificity.hs
- compiler/ghc.cabal.in
- distrib/configure.ac.in
- docs/users_guide/exts/literals.rst
- + docs/users_guide/exts/meaningful_main_return.rst
- docs/users_guide/exts/misc.rst
- docs/users_guide/using-warnings.rst
- ghc/Main.hs
- hadrian/bindist/Makefile
- hadrian/bindist/config.mk.in
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/Generate.hs
- libraries/base/src/GHC/Essentials.hs
- libraries/base/src/GHC/IO/Exception.hs
- libraries/base/src/System/Exit.hs
- libraries/containers
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- linters/lint-codes/LintCodes/Static.hs
- testsuite/driver/runtests.py
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/default/default-fail05.stderr
- + testsuite/tests/driver/T27836/A.hs
- + testsuite/tests/driver/T27836/B.hs
- + testsuite/tests/driver/T27836/C.hs
- + testsuite/tests/driver/T27836/Makefile
- + testsuite/tests/driver/T27836/T27836.stdout
- + testsuite/tests/driver/T27836/all.T
- + testsuite/tests/driver/T27836/unitA
- + testsuite/tests/driver/T27836/unitB
- + testsuite/tests/driver/T27836/unitC
- testsuite/tests/driver/T4437.hs
- + testsuite/tests/ghc-api/T4162.hs
- + testsuite/tests/ghc-api/T4162.stdout
- testsuite/tests/ghc-api/all.T
- + testsuite/tests/ghc-e/should_run/T9086.stderr
- testsuite/tests/ghci.debugger/scripts/T14628.stderr
- testsuite/tests/ghci/prog020/ghci.prog020a.stderr
- testsuite/tests/ghci/prog020/ghci.prog020b.stderr
- testsuite/tests/ghci/prog021/prog021a.stderr
- testsuite/tests/ghci/prog021/prog021b.stderr
- testsuite/tests/ghci/prog022/ghci.prog022a.stderr
- testsuite/tests/ghci/prog022/ghci.prog022b.stderr
- testsuite/tests/ghci/prog022/ghci.prog022c.stderr
- testsuite/tests/ghci/prog022/ghci.prog022d.stderr
- testsuite/tests/ghci/prog022/ghci.prog022e.stderr
- testsuite/tests/ghci/prog022/ghci.prog022f.stderr
- testsuite/tests/ghci/scripts/Defer02.stderr
- + testsuite/tests/hpc/instmeths/instmeths.hs
- + testsuite/tests/hpc/instmeths/instmeths.stdout
- + testsuite/tests/hpc/instmeths/test.T
- + testsuite/tests/impredicative/T27917.hs
- testsuite/tests/impredicative/all.T
- + testsuite/tests/indexed-types/should_compile/T27828.hs
- + testsuite/tests/indexed-types/should_compile/T27828a.hs
- + testsuite/tests/indexed-types/should_compile/T27828b.hs
- testsuite/tests/indexed-types/should_compile/all.T
- testsuite/tests/indexed-types/should_fail/T1897b.stderr
- testsuite/tests/indexed-types/should_fail/T9662.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- + testsuite/tests/meaningful-main-return/Imported.hs
- + testsuite/tests/meaningful-main-return/MainReturn_constrained_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_alias_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_bottom_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_bottom_enabled_run.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_code_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_exit_success_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_always_exit_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_invalid_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_invalid_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_stuck_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_family_stuck_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_invalid_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_invalid_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_imported_wrapped_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_int_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_int_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_newtype_disabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_newtype_enabled.stderr
- + testsuite/tests/meaningful-main-return/MainReturn_typeapp_disabled.stderr
- + testsuite/tests/meaningful-main-return/MeaningfulMainReturn.hs
- + testsuite/tests/meaningful-main-return/all.T
- testsuite/tests/module/mod130.stderr
- testsuite/tests/overloadedstrings/should_fail/T25926.stderr
- testsuite/tests/overloadedstrings/should_fail/T27124.stderr
- testsuite/tests/parser/should_compile/T7476/T7476.hs
- testsuite/tests/patsyn/should_fail/records-nofieldselectors.stderr
- testsuite/tests/printer/T17697.stderr
- testsuite/tests/rename/should_fail/T15607.stderr
- testsuite/tests/rename/should_fail/T19843b.stderr
- testsuite/tests/safeHaskell/ghci/p4.stderr
- testsuite/tests/safeHaskell/ghci/p6.stderr
- testsuite/tests/simplCore/should_compile/T22375.stderr
- testsuite/tests/simplCore/should_compile/T22375DataFamily.stderr
- testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs
- testsuite/tests/typecheck/should_compile/T11254.stderr
- testsuite/tests/typecheck/should_compile/T15370.stderr
- + testsuite/tests/typecheck/should_compile/T26543_orig.hs
- testsuite/tests/typecheck/should_compile/all.T
- + testsuite/tests/typecheck/should_compile/tc104.stderr
- testsuite/tests/typecheck/should_compile/valid_hole_fits.stderr
- testsuite/tests/typecheck/should_fail/ClassOperator.stderr
- testsuite/tests/typecheck/should_fail/DoExpansion2.stderr
- testsuite/tests/typecheck/should_fail/DoExpansion3.stderr
- testsuite/tests/typecheck/should_fail/FunDepOrigin1b.hs
- testsuite/tests/typecheck/should_fail/T12785b.stderr
- testsuite/tests/typecheck/should_fail/T18851.stderr
- + testsuite/tests/typecheck/should_fail/T18851e.hs
- + testsuite/tests/typecheck/should_fail/T18851e.stderr
- + testsuite/tests/typecheck/should_fail/T18851f.hs
- + testsuite/tests/typecheck/should_fail/T18851f.stderr
- testsuite/tests/typecheck/should_fail/T22707.stderr
- testsuite/tests/typecheck/should_fail/T22940.stderr
- + testsuite/tests/typecheck/should_fail/T26543a.hs
- + testsuite/tests/typecheck/should_fail/T26543a.stderr
- testsuite/tests/typecheck/should_fail/T26823.stderr
- + testsuite/tests/typecheck/should_fail/T27731.hs
- + testsuite/tests/typecheck/should_fail/T27731.stderr
- + testsuite/tests/typecheck/should_fail/T27844.hs
- + testsuite/tests/typecheck/should_fail/T27844.stderr
- testsuite/tests/typecheck/should_fail/T5691.stderr
- testsuite/tests/typecheck/should_fail/T7437.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_fail/mc24.stderr
- testsuite/tests/typecheck/should_fail/tcfail019.stderr
- testsuite/tests/typecheck/should_fail/tcfail189.stderr
- utils/check-exact/Parsers.hs
- utils/check-exact/Utils.hs
- utils/check-ppr/Main.hs
- utils/count-deps/Main.hs
- utils/dump-decls/Main.hs
- utils/haddock/haddock-api/src/Haddock.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.hs
- utils/haddock/haddock-api/test/Haddock/Backends/Hyperlinker/ParserSpec.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/9099eb8dce2c316538aac298bd1af7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/9099eb8dce2c316538aac298bd1af7…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/az/epa-tidy-locatedxxx-27] 15 commits: Remove the Eq and Ord instances for ForAllTyFlag
by Alan Zimmerman (@alanz) 14 Oct '26
by Alan Zimmerman (@alanz) 14 Oct '26
14 Oct '26
Alan Zimmerman pushed to branch wip/az/epa-tidy-locatedxxx-27 at Glasgow Haskell Compiler / GHC
Commits:
d07a5176 by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Remove the Eq and Ord instances for ForAllTyFlag
In Note [Comparing visibility] in GHC.Core.TyCo.Compare we read that
"we always compare ForAllTyFlags with `eqForAllVis` or `cmpForAllVis`"
But alas there was an Eq and Ord instance for ForAllTyFlag, which made it
impossible to check this claim. So I made these changes:
* Move the definition of ForAllTyFlag and its related functions from
L.H.S.Specificity (where it did not belong, since L.H.S didn't use it)
into GHC.Types.Var.
* Remove the Eq and Ord instances for ForAllTyFlag
* Deal with the fallout, by using `eqForAllVis` or related functions.
* In interface files we use IfaceType as a key for a de-deduplication map
See Note [Deduplication during iface binary serialisation]
in GHC.Iface.Binary. For this we need /exact/ comparison, so we use a
newtype wrapper for IfaceForAllTyFlag, and give use `cmpForAllTyFlagExactly`
to implement its Ord instance. Tiresome but easy.
* Rename `toIfaceForAllBndrs` to `toIfaceForAllTyBndrs`
- - - - -
ea5c054d by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Refactor type and coercion substitution
This MR refactors type and coercion substitution so that they use
TyCoMapper, rather than hand-rolled code. Fundamentally it's a simple
idea, but I had to do quite a bit of refactoring to make it fly.
I got Claude to help me this this refactoring, but I paid careful
attention to every line of code.
Main changes:
* New module GHC.Core.TyCo.Make which defines TyCoMapper, and a bunch of other
simple "smart constructors" for types and coercions. See
GHC.Core.TyCo.Rep Note [The Type-related module hierarchy], esp (TRM1)
* The new TyCoMapper has new fields `tcm_tcapp_ty` and `tcm_tcapp_co` to handle
type-constructor applications. These replace `tcm_tycon`.
* Rewrite GHC.Core.TyCo.Subst to use TyCoMapper
* Rewrite GHC.Core.Type.expandTypeSynonyms to use TyCoMapper.
* Implement `seqType` and `seqCo` with TyCoFolder. To to this I had to add
a `tcf_lit` field to TyCoFolder.
* A new module GHC.Utils.StrictIdentity to define a strict identity monad,
which itself is used for
substTyCoMapper :: TyCoMapper Subst StrictIdentity
* I removed an apparently-unused instance for Binary Levity
Refactoring `seq` functions
* In GHC.Core.Seq, redefine `seqOneShot`, `seqRuleInfo`, and friends to return
`SeqResult`, a new type defined in GHC.Types.Baseic, rather than `()`. We
can define a Monoid instance for `SeqResult` that does the right thing.
* This has knock-on effects across the compiler.
- - - - -
34165e23 by Simon Peyton Jones at 2026-10-13T18:10:39-04:00
Refactor TyCoMapper to take a single monad; add StrictReaderT
TyCoMapper used to be parameterised over both an environment and a
monad, with fields like
tcm_tyvar :: env -> TyVar -> m Type
Now it is parameterised over just the monad:
tcm_tyvar :: TyVar -> m Type
If the mapping needs an environment, `m` is a reader monad over that
environment. Many uses (e.g. zonkTcTypeMapper, swizzleMapper) need no
environment at all, and used to pass a dummy (). The binder field
becomes
tcm_tycobinder :: forall r. TyCoVar -> ForAllTyFlag
-> (TyCoVar -> m r) -> m r
and runs the continuation in the extended environment. mapTyCoX is gone;
only mapTyCo remains.
To make this efficient, the reader monad must use the one-shot trick and
be strict in the environment. So:
* New module GHC.Utils.Monad.StrictReader defines
newtype StrictReaderT r m a
with hand-written instances. The builder of the pattern synonym
`StrictReaderT` is a smart constructor that adds both `oneShot` and a
bang on the environment, so every StrictReaderT computation is strict
in the environment. See Note [Instances for StrictReaderT].
* ZonkT becomes type ZonkT = StrictReaderT ZonkEnv
ZonkM becomes type ZonkM = StrictReaderT ZonkGblEnv IO
replacing their own hand-written instances.
* Substitution uses
type SubstM = StrictReaderT Subst StrictIdentity
substTyCoMapper :: TyCoMapper SubstM
and similarly expandTypeSynonymMapper.
* zonk_tycomapper :: TyCoMapper (ZonkT TcM) is now much simpler.
* swizzleMapper uses StrictIdentity rather than Identity.
* Module renaming, so that the strict monads are all peers in GHC.Utils.Monad:
GHC.Utils.StrictIdentity ==> GHC.Utils.Monad.StrictIdentity
GHC.Utils.Monad.State.Strict ==> GHC.Utils.Monad.StrictState
alongside the new GHC.Utils.Monad.StrictReader.
Co-Authored-By: Claude Opus 5.5 <noreply(a)anthropic.com>
- - - - -
c0299e15 by Simon Jakobi at 2026-10-13T18:11:23-04:00
testsuite: Line-buffer the driver's stdout
Python block-buffers stdout when it is a pipe. This is the case for
example in CI. As a result there is often no indication of progress at
all until the run ends.
To fix this, we configure it explicitly to use line buffering instead.
stderr is reconfigured too, for consistency: Python line-buffers it by
default since 3.9.
The type-ignores are for mypy, which types these handles as TextIO — an
interface without reconfigure.
Fixes #12934.
Assisted-by: Claude Fable 5
- - - - -
9b5beaa2 by Florian Ragwitz at 2026-10-13T18:12:05-04:00
hpc: Improve coverage semantics for instance methods and instances
Users care about which of their explicitly written methods are or aren't
covered, not whether all of the inherited methods are covered as well. Those
should be covered where they are implemented.
We therefore skip generating top-level boxes for inherited methods which will
appear as uncovered with no clear indication as to why, and no way to fix other
than exercising code the user has not written.
Previously, top-level boxes for those inherited methods would use the instance
head as their source span. Now that those boxes are gone, we can use that
source span for another purpose:
We introduce a new top-level box for each class instance with its instance head
as the source span, and use that to indicate whether or not an instance has
been covered at all.
We do this by making any method of the instance, inherited/generated or
otherwise, tick the box for the instance head. Excluded from this are
methodless classes, which could never be covered using the current mechanism.
This could be improved upon further.
These changes apply to ticking for program coverage only, and don't affect
source notes. Additionally, we update the scope of record selector ticking to
be limited to program coverage as well, as the oversight to also extend it to
source notes has previously caused bugs and because record selector ticking is
coverage-specific.
Fixes #17155, #15932.
- - - - -
836ec50a by Simon Peyton Jones at 2026-10-13T18:12:54-04:00
Refactor fundeps again
This MR fixes #27828; there was a bad scoping error in `trim_qtvs`.
The main changes are
* Refactor `trim_qtvs` completely to eliminate the bug.
* Remove a redundant `apartnessCheck` from `mkTopOpenFamEqFDs`.
* Lots of improvements to the Notes in FunDeps.hs
I also did a couple of pure refactors:
* I realised that we were carefully caching `cab_incomps` in each
`CoAxBranch`, to make it more efficient to reduce a type family application,
but we were not doing the same thing when computing relevance for functional
dependencies; see Note [Relevance] in GHC.Tc.Solver.FunDeps. So I added
`cab_overlaps`, which is now used in `noEarlierMatch`.
* Use a proper data types, `AmIUnifying` and `OuterKindsFlag`, for two
previously-Boolean arguments to `tc_unify_tys`. This is a pure refactor.
- - - - -
889ef371 by Simon Peyton Jones at 2026-10-13T18:13:36-04:00
Refactor and simplify solver's unification code
Ticket #27844 showed that GHC's constraint solver could miss an
occurs check, and thereby build an infinite type.
This patch significantly simplifes the code in
GHC.Tc.Solver.Equality.canEqCanLHSFinish_try_unification
GHC.Tc.Solver.Equality.canEqCanLHSFinish_no_unification
It is now significantly simpler, and requires much less subtle
reasoning to understand.
Main changes
* If `canEqCanLHSFinish_try_unification` fails to unify, it now /always/ calls
`canEqCanLHSFinish_no_unification` rather than trying to finish the job itself.
* `GHC.Tc.Solver.Monad.checkTypeEq` is moved from Monad into Equality, and renamed
to `GHC.Tc.Solver.Equality.checkTypeEqNoUnification`.
* `canEqCanLHSFinish_no_unification` calls `checkTypeEqNoUnification` to test
the invariants for an inert equality. Before this MR there was a special case for
`do_not_prevent_rewriting`, but that has gone; instead it's just a consequence of
the flags passed to `checkTyEqRhs`, documented in the `PuOK` case of
`canEqCanLHSFinish_no_unification`.
* There is only one bit of "swap back" code, in `finish_no_unify` in
`canEqCanLHSFinish_try_unification. Previously this code was duplicated.
* `kickOutAfterFillingCoercionHole` should account for equalities with a
TyFamLHS. See (KOC5) in Note [Kick out after filling a coercion hole]
* No need to gather coercion holes in the `PuOK` case of `canEqCanLHSFinish_no_unification`.
See documentation with that code.
- - - - -
f9193e53 by Simon Peyton Jones at 2026-10-13T18:13:37-04:00
One line fix to fallout from
...#27731, !16564, simplifying Tc.Errors machinery
There was an over-eager assert!
- - - - -
cdd56b7a by Florian Ragwitz at 2026-10-13T18:14:19-04:00
Fix several sphinx errors and warnings from rendering the release notes
The extension references which are removed here are for extension which were
already previously undocumented, so just removing them seems fine for now.
- - - - -
4f00da25 by Florian Ragwitz at 2026-10-13T18:14:19-04:00
Link to QualifiedStrings documentation
- - - - -
97adaf89 by Simon Peyton Jones at 2026-10-14T00:07:27+01:00
Line up simpleUnifyCheck and check_ty_eq_rhs
Even after #26543 was allegedly fixed, the original repo case in the
Description continued to fail. The reason was that the QuickLook
unifier, `qlUnify`, used `simpleUnifyCheck` for checking unification
invariants; and `simpleUnifyCheck` conservatively rejected any RHS
with a coercion hole in it. The upshot was that QuickLook was not
as clever as it should be, wrongly failing to do an impredicative
instantiation.
Interestingly `check_ty_eq_rhs`, which does the same job during
constraint solving, was more liberal: it just looked at the free vars
of the coercion, and allowed coercion holes.
This MR lines them up, adding some careful notes. See
Note [simpleUnifyCheck]
Note [Occurs check and coercions]
Note [Unification preconditions] esp (COERCIONS)
Things are better than before, but I am still uncomfortable about the
possibilty that a hole might be filled with a coercion that mentions
the LHS type variable; for now I have left this discomfort documented
in Note [Occurs check and coercions].
Main changes
* `qlUnify` now only unifies /instantiation variables/ not regular unification
variables. This makes QuickLook more predictable. See (UQL6) in
Note [QuickLook unification].
* `qlUnify` no longer needs to call `simpleUnifyCheck`, so we can get rid of
`UC_QuickLook` and its code in `simpleUnifyCheck`.
* I found I could get rid of `mkOccFolders` in favour of `anyFreeVarsOfType`.
Hooray.
* Improve documentation of CycleBreakerTv, and rename it to GivenCycleBreakerTv
because they are only uesd for Givens!
* I accepted a 9% worsening in compile time allocation on T5030
because the newly-consistent story triggered #27934.
Other changes
* I refactored `atvFolder` so that it pairs the "interesting-var" function
with the in-scope set, to avoid building a closure with a free variable.
Now we get nice tight loops for `anyFreeVarsOfType` and friends.
See Note [Any-free-var folder].
Metric Increase:
T5030
- - - - -
5f7b3047 by Simon Peyton Jones at 2026-10-14T00:07:27+01:00
Fix order-dependence in QuickLook
Ticket #27917 pointed out that QuickLook was order-dependent
-- very bad!
The solution is in `qlUnify`: spot when we are unifying a type with a
definite monotype, and then monomorphise any free instantiation
variables of that type.
See (UQL8) and (UQL9) in Note [QuickLook unification].
- - - - -
c391c70c by Simon Peyton Jones at 2026-10-14T00:07:28+01:00
Add some comments about RuntimeUnk
This commit just adds comments explaining why we don't need to worry about
RuntimeUnkTv in the constraint solver.
It also tightens up docmentation of earlier (overlapping) commits in
this MR.
- - - - -
7df3ba2f by Andrea Vezzosi at 2026-10-14T06:15:48-04:00
add runGhcWithSignalHandlers and remove handling from runGhc[T]
it only ever makes sense to call `withSignalHandlers` from `main`, otherwise
signals can be too easily swallowed without notification to the rest of your
process.
This commit takes withSignalHandlers out of `runGhc/runGhcT` and provides
`runGhcWithSignalHandlers` for the old behaviour.
- - - - -
47dd0233 by Alan Zimmerman at 2026-10-14T18:07:07+01:00
EPA: Start using vocurly as basis for AnnListLayout
For the existing cases that populate AnnList.
This uses AnnListBraces when braces are explicitly supplied, and
AnnListLayout when vocurly is used
The change also shows up AnnList usages that can never capture layout,
these are cleared up later.
- - - - -
158 changed files:
- changelog.d/26616
- + changelog.d/T26543
- changelog.d/T27329
- + changelog.d/T27828
- + changelog.d/T27844
- + changelog.d/T4162
- changelog.d/boxing-family
- + changelog.d/hpc-classinsts
- changelog.d/tcplugin_init.md
- changelog.d/unit-index
- compiler/GHC.hs
- compiler/GHC/Builtin/WiredIn/Prim.hs
- compiler/GHC/Builtin/WiredIn/Types/Box.hs
- compiler/GHC/Cmm/GenericOpt.hs
- compiler/GHC/Cmm/UniqueRenamer.hs
- compiler/GHC/CmmToAsm/Dwarf/Types.hs
- compiler/GHC/CmmToAsm/Monad.hs
- compiler/GHC/CmmToAsm/Reg/Graph/Spill.hs
- compiler/GHC/CmmToAsm/Reg/Graph/SpillClean.hs
- compiler/GHC/CmmToAsm/Reg/Graph/SpillCost.hs
- compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs
- compiler/GHC/CmmToAsm/Reg/Linear/State.hs
- compiler/GHC/CmmToAsm/Reg/Linear/Stats.hs
- compiler/GHC/CmmToAsm/Reg/Liveness.hs
- compiler/GHC/CmmToAsm/Wasm/Asm.hs
- compiler/GHC/CmmToAsm/Wasm/Types.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion.hs-boot
- compiler/GHC/Core/Coercion/Axiom.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Map/Type.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/CallerCC.hs
- compiler/GHC/Core/Opt/Exitify.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Reduction.hs
- compiler/GHC/Core/Seq.hs
- compiler/GHC/Core/TyCo/Compare.hs
- compiler/GHC/Core/TyCo/FVs.hs
- + compiler/GHC/Core/TyCo/Make.hs
- + compiler/GHC/Core/TyCo/Make.hs-boot
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCo/Rep.hs-boot
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Type.hs-boot
- compiler/GHC/Core/Unify.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToIface.hs-boot
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Main/Compile.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Types.hs
- compiler/GHC/Iface/Ext/Utils.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Iface/Type.hs-boot
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Parser.y
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Stg/BcPrep.hs
- compiler/GHC/Stg/Debug.hs
- compiler/GHC/Stg/EnforceEpt/Rewrite.hs
- compiler/GHC/Stg/EnforceEpt/TagSig.hs
- compiler/GHC/Stg/Subst.hs
- compiler/GHC/Tc/Deriv/Functor.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Instance/FunDeps.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/Env.hs
- compiler/GHC/Tc/Zonk/Monad.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/Types/Arity.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Cpr.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Name/Env.hs
- compiler/GHC/Types/Name/Occurrence.hs
- compiler/GHC/Types/Unique/DSM.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Unique/Map.hs
- compiler/GHC/Types/Unique/Set.hs
- compiler/GHC/Types/Unique/Supply.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Types/Var.hs-boot
- compiler/GHC/Types/Var/FV.hs
- compiler/GHC/Types/Var/Set.hs
- compiler/GHC/Utils/Binary.hs
- + compiler/GHC/Utils/Monad/StrictIdentity.hs
- + compiler/GHC/Utils/Monad/StrictReader.hs
- compiler/GHC/Utils/Monad/State/Strict.hs → compiler/GHC/Utils/Monad/StrictState.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/GHC/Utils/Panic.hs
- compiler/Language/Haskell/Syntax/Specificity.hs
- compiler/ghc.cabal.in
- docs/users_guide/exts/literals.rst
- ghc/Main.hs
- linters/lint-codes/LintCodes/Static.hs
- testsuite/driver/runtests.py
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/default/default-fail05.stderr
- + testsuite/tests/ghc-api/T4162.hs
- + testsuite/tests/ghc-api/T4162.stdout
- testsuite/tests/ghc-api/all.T
- testsuite/tests/ghci.debugger/scripts/T14628.stderr
- + testsuite/tests/hpc/instmeths/instmeths.hs
- + testsuite/tests/hpc/instmeths/instmeths.stdout
- + testsuite/tests/hpc/instmeths/test.T
- + testsuite/tests/impredicative/T27917.hs
- testsuite/tests/impredicative/all.T
- + testsuite/tests/indexed-types/should_compile/T27828.hs
- + testsuite/tests/indexed-types/should_compile/T27828a.hs
- + testsuite/tests/indexed-types/should_compile/T27828b.hs
- testsuite/tests/indexed-types/should_compile/all.T
- testsuite/tests/indexed-types/should_fail/T1897b.stderr
- testsuite/tests/indexed-types/should_fail/T9662.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/simplCore/should_compile/T22375.stderr
- testsuite/tests/simplCore/should_compile/T22375DataFamily.stderr
- testsuite/tests/typecheck/should_compile/LocalGivenEqs.hs
- + testsuite/tests/typecheck/should_compile/T26543_orig.hs
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_fail/T12785b.stderr
- testsuite/tests/typecheck/should_fail/T22707.stderr
- + testsuite/tests/typecheck/should_fail/T26543a.hs
- + testsuite/tests/typecheck/should_fail/T26543a.stderr
- + testsuite/tests/typecheck/should_fail/T27844.hs
- + testsuite/tests/typecheck/should_fail/T27844.stderr
- testsuite/tests/typecheck/should_fail/all.T
- utils/check-exact/Parsers.hs
- utils/check-exact/Utils.hs
- utils/check-ppr/Main.hs
- utils/count-deps/Main.hs
- utils/dump-decls/Main.hs
- utils/haddock/haddock-api/src/Haddock.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Utils.hs
- utils/haddock/haddock-api/test/Haddock/Backends/Hyperlinker/ParserSpec.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e8f40ee0619a88c016f3c2a31f1b92…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e8f40ee0619a88c016f3c2a31f1b92…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 4 commits: Fix #27836, normalise unit database path in ExternalUnitDatabases
by Marge Bot (@marge-bot) 14 Oct '26
by Marge Bot (@marge-bot) 14 Oct '26
14 Oct '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
3a72b8a2 by Hannes Siebenhandl at 2026-10-14T13:48:32-04:00
Fix #27836, normalise unit database path in ExternalUnitDatabases
Add a regression test, proofing that all variations:
- local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf/
are parsed only once.
- - - - -
8ddbc6f9 by Florian Ragwitz at 2026-10-14T13:49:28-04:00
Remove obsolete HPC types
Fixes #27946.
- - - - -
a3d802b3 by sheaf at 2026-10-14T14:21:27-04:00
Make exprFreeVars deep
exprFreeVars used to be a shallow free-variable finder (it didn't look
into kinds), but most callers wanted it to be deep. In particular,
'exprFreeVars' is often used to seed an 'InScopeSet', and that must
contain the /deep/ free variables.
This commit makes it deep, which allows us to get rid of calls to
'closeOverKinds' or other workarounds for shallowness in:
- 'GHC.Core.Opt.Simplify.Utils.abstractFloats'
- 'GHC.HsToCore.Binds.dsSpec_help'
- 'GHC.Core.Opt.Arity.etaBodyForJoinPoint'
- 'GHC.Core.FVs.freeVars'
- 'GHC.Core.Lint.lintCoreRule'
We also remove 'deepExprsFreeVarsDSet' and 'closeOverKindsDSet'.
Other places needed a little bit more care, in particular to properly
handle coercion variables free in kinds:
- 'GHC.Core.Opt.Specialise.specHeader' quantifies over the binder of
an unspecialised argument directly, instead of computing the free Ids
of the argument.
- 'GHC.HsToCore.dsWarnRuleShadowing' filters out 'CoVar's.
- 'GHC.Core.Opt.SpecConstr.callToPat' had some ad-hoc logic to compute
argument pattern types and a workaround with 'expandTypeSynonyms'.
That logic is removed in favour of a new 'argsToPats' function which
directly computes the argument pattern types by instantiating the
type of the head of the call pattern.
Fixes #27936
- - - - -
b877a9b0 by Luite Stegeman at 2026-10-14T14:21:40-04:00
testsuite: Use mkWeakMVar in memo001/memo002
mkWeakPtr in the memo001/memo001 tests created weak pointers
with the MVar box as the key, which is fragile in the presence
of optimization. The fix is using mkWeakMVar, keying on the
primitive MVar# instead.
Fixes #27924 and #27396
- - - - -
36 changed files:
- + changelog.d/27936
- + changelog.d/hpc-cleanup
- changelog.d/unit-index
- compiler/GHC/Core/FVs.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/TyCo/FVs.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg.hs
- compiler/GHC/Data/OsPath.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/StgToJS/ExprCtx.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Var/FV.hs
- compiler/GHC/Unit/External/Database.hs
- libraries/base/tests/Memo1.lhs
- libraries/base/tests/Memo2.lhs
- libraries/base/tests/all.T
- + testsuite/tests/driver/T27836/A.hs
- + testsuite/tests/driver/T27836/B.hs
- + testsuite/tests/driver/T27836/C.hs
- + testsuite/tests/driver/T27836/Makefile
- + testsuite/tests/driver/T27836/T27836.stdout
- + testsuite/tests/driver/T27836/all.T
- + testsuite/tests/driver/T27836/unitA
- + testsuite/tests/driver/T27836/unitB
- + testsuite/tests/driver/T27836/unitC
- + testsuite/tests/simplCore/should_compile/T27936.hs
- testsuite/tests/simplCore/should_compile/all.T
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/821e573035020a6902cdacee381564…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/821e573035020a6902cdacee381564…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/int-index/curried-ctxts] Curried contexts in prefix GADT constructors
by Vladislav Zavialov (@int-index) 14 Oct '26
by Vladislav Zavialov (@int-index) 14 Oct '26
14 Oct '26
Vladislav Zavialov pushed to branch wip/int-index/curried-ctxts at Glasgow Haskell Compiler / GHC
Commits:
bb2c9f35 by Vladislav Zavialov at 2026-10-14T20:05:35+02:00
Curried contexts in prefix GADT constructors
Prefix GADT constructor declarations now accept multiple consecutive
contexts, equivalent to a single conjoined context:
data G a where
MkCurried :: C a => (D a, E a) => G a
MkConjoined :: (C a, D a, E a) => G a
This is a step towards GHC Proposal #402 "Stable GADT constructor syntax".
To represent multiple contexts, the `con_mb_cxt` field of `ConDeclGADT` has
been replaced by `con_cxts`, which stores a list instead of a Maybe:
- con_mb_cxt :: Maybe (LHsContext pass)
+ con_cxts :: [LHsContext pass]
The rest of this patch follows from this change.
Note that in ConDeclH98, the optional context is still stored as a Maybe.
To accommodate this difference, a few helper functions were generalised over
a Foldable container `t`:
hsConDeclTheta :: Foldable t => t (LHsContext ...) -> [LHsType ...]
pprLHsContext :: (Foldable t, ...) => t (LHsContext ...) -> SDoc
repContexts :: Foldable t => t (LHsContext GhcRn) -> MetaM (Core (M TH.Cxt))
tcHsContext :: Foldable t => t (LHsContext GhcRn) -> TcM [PredType]
In practice, the instantiations of `t` are either `Maybe` or `[]`.
Record-style GADT constructors continue to accept at most one context.
`splitLHsGadtTy` accounts for this by splitting off only the first context
if it detects record syntax, leaving the offending part of the type in the
body for the renamer to reject later on.
- - - - -
20 changed files:
- changelog.d/allow-gadt-prefix-con-parens
- + changelog.d/gadt-curried-contexts-27424
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/ThToHs.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Type.hs
- docs/users_guide/exts/gadt_syntax.rst
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.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
Changes:
=====================================
changelog.d/allow-gadt-prefix-con-parens
=====================================
@@ -6,7 +6,7 @@ mrs: !16321
description:
Parenthesized types are now accepted in prefix GADT constructor declarations,
- even when they contain explicit ``forall`` quantifiers. For example:
+ even when they contain explicit ``forall`` quantifiers. For example::
data T where
MkT :: (forall a. a -> b -> T)
=====================================
changelog.d/gadt-curried-contexts-27424
=====================================
@@ -0,0 +1,15 @@
+section: language
+synopsis: Allow multiple consecutive contexts in prefix GADT constructor declarations (GHC Proposal `#402 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0402-g…>`_ "Stable GADT constructor syntax")
+issues: #27424
+mrs: !16819
+
+description: {
+ Prefix GADT constructor declarations now accept multiple consecutive contexts,
+ equivalent to a single conjoined context. For example::
+
+ data G a where
+ MkCurried :: C a => (D a, E a) => G a
+ MkConjoined :: (C a, D a, E a) => G a
+
+ Record-style GADT constructor declarations continue to accept at most one context.
+}
=====================================
compiler/GHC/Hs/Decls.hs
=====================================
@@ -886,9 +886,8 @@ getRecConArgs_maybe (ConDeclGADT{con_g_args = args}) = case args of
PrefixConGADT{} -> Nothing
RecConGADT _ flds -> Just flds
-hsConDeclTheta :: Maybe (LHsContext (GhcPass p)) -> [LHsType (GhcPass p)]
-hsConDeclTheta Nothing = []
-hsConDeclTheta (Just (L _ (HsContext _ theta))) = theta
+hsConDeclTheta :: Foldable t => t (LHsContext (GhcPass p)) -> [LHsType (GhcPass p)]
+hsConDeclTheta = concatMap (hsc_ctxt . unLoc)
ppDataDefnHeader
:: (OutputableBndrId p)
@@ -971,11 +970,11 @@ pprConDecl (ConDeclH98 { con_name = L _ con
pprConDecl (ConDeclGADT { con_names = cons
, con_outer_bndrs = L _ outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt, con_g_args = args
+ , con_cxts = cxts, con_g_args = args
, con_res_ty = res_ty, con_modifiers = mods, con_doc = doc })
= pprMaybeWithDoc doc $ pprLHsModifiers mods <+> ppr_con_names (toList cons) <+> dcolon
<+> sep [ppr_outer_bndrs, ppr_inner_bndrs (
- sep [ pprLHsContext mcxt,
+ sep [ pprLHsContext cxts,
sep (ppr_args args ++ [ppr res_ty])])]
where
ppr_args (PrefixConGADT _ args) = map (pprHsConDeclFieldWith (\arr tyDoc -> tyDoc <+> pprHsModifiedFunArr arr)) args
=====================================
compiler/GHC/Hs/Type.hs
=====================================
@@ -126,6 +126,7 @@ import GHC.Utils.Misc (count)
import Data.Maybe
import Data.Data (Data)
+import Data.Foldable ( toList )
import qualified Data.Semigroup as S
import GHC.Data.Bag
@@ -896,7 +897,7 @@ splitLHsSigmaTyInvis ty
= (tvs, ctxt, ty2)
-- | Decompose a GADT type into its constituent parts.
--- Returns @(outer_bndrs, inner_bndrs, mb_ctxt, body)@, where:
+-- Returns @(outer_bndrs, inner_bndrs, ctxts, body)@, where:
--
-- * @outer_bndrs@ are 'HsOuterExplicit' if the type has explicit, outermost
-- type variable binders. Otherwise, they are 'HsOuterImplicit'.
@@ -904,10 +905,9 @@ splitLHsSigmaTyInvis ty
-- * @inner_bndrs@ are the remaining @forall@ telescopes, interleaved with the
-- parentheses that enclose them.
--
--- * @mb_ctxt@ is @Just@ the context, if it is provided.
--- Otherwise, it is @Nothing@.
+-- * @ctxts@ are the contexts adjacent to the @forall@s, if any.
--
--- * @body@ is the body of the type after the optional @forall@s and context.
+-- * @body@ is the body of the type after the optional @forall@s and contexts.
--
-- This function does look through parentheses, but it does not discard them:
-- they are syntactically significant, so they are recorded in @inner_bndrs@.
@@ -915,16 +915,22 @@ splitLHsSigmaTyInvis ty
-- in "GHC.Hs.Decls" for why this is important.
splitLHsGadtTy ::
LHsSigType GhcPs
- -> (HsOuterSigTyVarBndrs GhcPs, [LHsGadtTelescope GhcPs], Maybe (LHsContext GhcPs), LHsType GhcPs)
+ -> (HsOuterSigTyVarBndrs GhcPs, [LHsGadtTelescope GhcPs], [LHsContext GhcPs], LHsType GhcPs)
splitLHsGadtTy (L _ sig_ty)
| (outer_bndrs, sigma_ty) <- split_outer_bndrs sig_ty
, (inner_bndrs, phi_ty) <- split_inner_bndrs sigma_ty
- , (mb_ctxt, rho_ty) <- splitLHsQualTy_KP phi_ty
- = if is_gadt_rec_ty rho_ty && not (null inner_bndrs)
- -- Bad! Record GADTs are not allowed to have inner_bndrs,
- -- undo the split to get a proper error message later
- then (outer_bndrs, [], Nothing, sigma_ty)
- else (outer_bndrs, inner_bndrs, mb_ctxt, rho_ty)
+ , (outer_theta, phi_ty') <- splitLHsQualTy_KP phi_ty
+ , (inner_theta, rho_ty) <- split_ctxts phi_ty'
+ = case rho_ty of
+ -- Record GADTs are not allowed to have multiple foralls or contexts.
+ -- Detect and undo the split to get a proper error message later.
+ L _ (HsFunTy _ _ (L _ (XHsType HsRecTy{})) _)
+ | not (null inner_bndrs) -> (outer_bndrs, [], [], sigma_ty)
+ | not (null inner_theta) -> (outer_bndrs, inner_bndrs, toList outer_theta, phi_ty')
+ -- All good: either a prefix GADT con, or a record GADT con with at most
+ -- one forall and at most one context.
+ _ -> let theta_tys = toList outer_theta ++ inner_theta
+ in (outer_bndrs, inner_bndrs, theta_tys, rho_ty)
where
split_outer_bndrs :: HsSigType GhcPs -> (HsOuterSigTyVarBndrs GhcPs, LHsType GhcPs)
split_outer_bndrs (HsSig{sig_bndrs = outer_bndrs, sig_body = body_ty}) =
@@ -941,9 +947,10 @@ splitLHsGadtTy (L _ sig_ty)
in (L l (HsGadtPar toks) : args, t)
split_inner_bndrs t = ([], t)
- -- type of form {fld :: ty, ...} -> ResTy
- is_gadt_rec_ty (L _ (HsFunTy _ _ (L _ (XHsType HsRecTy{})) _)) = True
- is_gadt_rec_ty _ = False
+ split_ctxts :: LHsType GhcPs -> ([LHsContext GhcPs], LHsType GhcPs)
+ split_ctxts (L _ HsQualTy { hst_ctxt = ctxt, hst_body = body })
+ = let { ~(ctxts, t) = split_ctxts body } in (ctxt : ctxts, t)
+ split_ctxts t = ([], t)
-- | Decompose a type of the form @forall <tvs>. body@ into its constituent
-- parts. Only splits type variable binders that
@@ -1426,10 +1433,9 @@ pprHsForAllTelescope tele =
-- be updated to match.
| otherwise = forAllLit <+> interppSP qtvs <> separator
-pprLHsContext :: (OutputableBndrId p)
- => Maybe (LHsContext (GhcPass p)) -> SDoc
-pprLHsContext Nothing = empty
-pprLHsContext (Just lctxt) = pprLHsContextAlways lctxt
+pprLHsContext :: (Foldable t, OutputableBndrId p)
+ => t (LHsContext (GhcPass p)) -> SDoc
+pprLHsContext = sep . map pprLHsContextAlways . toList
-- For use in a HsQualTy, which always gets printed if it exists.
pprLHsContextAlways :: (OutputableBndrId p)
=====================================
compiler/GHC/HsToCore/Quote.hs
=====================================
@@ -888,7 +888,7 @@ repC (L _ (ConDeclH98 { con_name = con
, con_args = args }))
= addHsTyVarBinds FreshNamesOnly con_tvs $ \ ex_bndrs ->
do { c' <- repH98DataCon con args
- ; ctxt' <- repMbContext mcxt
+ ; ctxt' <- repContexts mcxt
; if not is_existential && isNothing mcxt
then return c'
else rep2 forallCOcc ([unC ex_bndrs, unC ctxt', unC c'])
@@ -897,7 +897,7 @@ repC (L _ (ConDeclH98 { con_name = con
repC (L l (ConDeclGADT { con_names = cons
, con_outer_bndrs = L _ outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = res_ty }))
| no_explicit_forall, no_context
@@ -908,9 +908,9 @@ repC (L l (ConDeclGADT { con_names = cons
| Just invis_inner_bndrs <- m_invis_inner_bndrs
= addHsOuterSigTyVarBinds outer_bndrs $ \ outer_bndrs' ->
- -- the context is attached to the innermost ForallC
+ -- the contexts are flattened and attached to the innermost ForallC
let loop last_bndrs' [] = do
- ctxt' <- repMbContext mcxt
+ ctxt' <- repContexts cxts
c' <- repGadtDataCons cons args res_ty
rep2 forallCOcc ([unC last_bndrs', unC ctxt', unC c'])
loop last_bndrs' (bndrs : bndrs_s) =
@@ -927,7 +927,7 @@ repC (L l (ConDeclGADT { con_names = cons
inner_teles = gadtArgTelescopes inner_bndrs
no_explicit_forall = nullOuterExplicit outer_bndrs && null inner_teles
- no_context = isNothing mcxt
+ no_context = null cxts
m_invis_inner_bndrs :: Maybe [[LHsTyVarBndr Specificity GhcRn]]
m_invis_inner_bndrs = traverse get_invis_bndrs inner_teles
@@ -936,9 +936,9 @@ repC (L l (ConDeclGADT { con_names = cons
get_invis_bndrs HsForAllVis{} = Nothing
get_invis_bndrs HsForAllInvis { hsf_invis_bndrs = tvbs } = Just tvbs
-repMbContext :: Maybe (LHsContext GhcRn) -> MetaM (Core (M TH.Cxt))
-repMbContext Nothing = repContext emptyContext
-repMbContext (Just (L _ cxt)) = repContext cxt
+-- | Flatten several contexts into a single 'TH.Cxt'.
+repContexts :: Foldable t => t (LHsContext GhcRn) -> MetaM (Core (M TH.Cxt))
+repContexts cxts = repContext $ HsContext noAnn (hsConDeclTheta cxts)
repSrcUnpackedness :: SrcUnpackedness -> MetaM (Core (M TH.SourceUnpackedness))
repSrcUnpackedness SrcUnpack = rep2 sourceUnpackOcc []
=====================================
compiler/GHC/Iface/Ext/Ast.hs
=====================================
@@ -1761,7 +1761,7 @@ instance ToHie (LocatedA (ConDecl GhcRn)) where
ConDeclGADT { con_names = names
, con_outer_bndrs = L outer_bndrs_loc outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = ctx
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = typ
, con_doc = doc} ->
@@ -1770,14 +1770,14 @@ instance ToHie (LocatedA (ConDecl GhcRn)) where
map (C $ TyVarBind (mkScope outer_bndrs_loc) (ResolvedScopes [sigmaScope]))
imp_vars
, toHie $ tvScopes (ResolvedScopes [phiScope]) NoScope exp_bndrs
- , toHie ctx
+ , toHie cxts
, toHie args
, toHie typ
, toHie doc
]
where
rhsScope = combineScopes argsScope tyScope
- ctxScope = maybe NoScope mkScope ctx
+ ctxScope = foldr combineScopes NoScope (map mkScope cxts)
argsScope = case args of
PrefixConGADT _ xs -> scaled_args_scope xs
RecConGADT _ x -> mkScope x
=====================================
compiler/GHC/Parser/PostProcess.hs
=====================================
@@ -833,13 +833,13 @@ mkGadtDecl loc mods names dcol ty = do
, con_names = names
, con_outer_bndrs = L outer_bndrs_loc outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = res_ty
, con_modifiers = mods
, con_doc = Nothing }
where
- (outer_bndrs, inner_bndrs, mcxt, body_ty) = splitLHsGadtTy ty
+ (outer_bndrs, inner_bndrs, cxts, body_ty) = splitLHsGadtTy ty
outer_bndrs_loc = case outer_bndrs of
HsOuterImplicit{} -> getLoc ty
HsOuterExplicit an _ -> EpAnn (entry an) noAnn emptyComments
=====================================
compiler/GHC/Parser/PostProcess/Haddock.hs
=====================================
@@ -694,7 +694,7 @@ instance HasHaddock (LocatedA (ConDecl GhcPs)) where
extendHdkA (locA l_con_decl) $
case con_decl of
ConDeclGADT { con_g_ext, con_names, con_outer_bndrs, con_inner_bndrs
- , con_mb_cxt, con_g_args, con_res_ty, con_modifiers } -> do
+ , con_cxts, con_g_args, con_res_ty, con_modifiers } -> do
con_doc' <- getConDoc (getLocA (NE.head con_names))
con_g_args' <-
case con_g_args of
@@ -705,7 +705,7 @@ instance HasHaddock (LocatedA (ConDecl GhcPs)) where
con_res_ty' <- addHaddock con_res_ty
pure $ L l_con_decl $
ConDeclGADT { con_g_ext, con_names,
- con_outer_bndrs, con_inner_bndrs, con_mb_cxt, con_modifiers,
+ con_outer_bndrs, con_inner_bndrs, con_cxts, con_modifiers,
con_doc = lexLHsDocString <$> con_doc',
con_g_args = con_g_args',
con_res_ty = con_res_ty' }
=====================================
compiler/GHC/Rename/Module.hs
=====================================
@@ -28,7 +28,8 @@ import GHC.Rename.HsType
import GHC.Rename.Bind
import GHC.Rename.Doc
import GHC.Rename.Env
-import GHC.Rename.Utils ( mapFvRn, bindLocalNames
+import GHC.Rename.Utils ( mapFvRn, mapMaybeFvRn
+ , bindLocalNames
, checkDupRdrNames, bindLocalNamesFV
, warnUnusedTypePatterns
, noNestedForallsContextsErr
@@ -2615,7 +2616,7 @@ rnConDecl decl@(ConDeclH98 { con_name = name, con_ex_tvs = ex_tvs
; let ctxt = ConDeclCtx [new_name]
; bindLHsTyVarBndrs ctxt WarnUnusedForalls
Nothing ex_tvs $ \ new_ex_tvs ->
- do { (new_context, fvs1) <- rnMbContext ctxt mcxt
+ do { (new_context, fvs1) <- mapMaybeFvRn (rnContext ctxt) mcxt
; (new_args, fvs2) <- rnConDeclH98Details (unLoc new_name) ctxt args
; (mods', mods_fvs) <- rnModifiersContextAndWarn ctxt mods
; let all_fvs = fvs1 `plusFN` fvs2 `plusFN` mods_fvs
@@ -2635,7 +2636,7 @@ rnConDecl decl@(ConDeclH98 { con_name = name, con_ex_tvs = ex_tvs
rnConDecl (ConDeclGADT { con_names = names
, con_outer_bndrs = L outer_bndrs_loc outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = res_ty
, con_modifiers = mods
@@ -2651,7 +2652,7 @@ rnConDecl (ConDeclGADT { con_names = names
implicit_bndrs =
extractHsOuterTvBndrs outer_bndrs $
extractHsGadtTelescopes inner_bndrs $
- extractHsTysRdrTyVars (hsConDeclTheta mcxt) $
+ extractHsTysRdrTyVars (hsConDeclTheta cxts) $
extractConDeclGADTDetailsTyVars args $
extractHsTysRdrTyVars [res_ty] []
@@ -2659,7 +2660,7 @@ rnConDecl (ConDeclGADT { con_names = names
; bindHsOuterTyVarBndrs ctxt Nothing implicit_bndrs outer_bndrs $ \outer_bndrs' ->
bindHsGadtTelescopes ctxt inner_bndrs $ \inner_bndrs' ->
- do { (new_cxt, fvs1) <- rnMbContext ctxt mcxt
+ do { (new_cxts, fvs1) <- mapFvRn (rnContext ctxt) cxts
; (new_args, fvs2) <- rnConDeclGADTDetails (unLoc (head new_names)) ctxt args
; (new_res_ty, fvs3) <- rnLHsType ctxt res_ty
; (mods', mods_fvs) <- rnModifiersContextAndWarn ctxt mods
@@ -2678,17 +2679,11 @@ rnConDecl (ConDeclGADT { con_names = names
; return (ConDeclGADT { con_g_ext = noExtField, con_names = new_names
, con_outer_bndrs = L outer_bndrs_loc outer_bndrs'
, con_inner_bndrs = inner_bndrs'
- , con_mb_cxt = new_cxt
+ , con_cxts = new_cxts
, con_g_args = new_args, con_res_ty = new_res_ty
, con_doc = new_mb_doc, con_modifiers = mods' },
all_fvs) } }
-rnMbContext :: HsDocContext -> Maybe (LHsContext GhcPs)
- -> RnM (Maybe (LHsContext GhcRn), FreeNames)
-rnMbContext _ Nothing = return (Nothing, emptyFNs)
-rnMbContext doc cxt = do { (ctx',fvs) <- rnMaybeContext doc cxt
- ; return (ctx',fvs) }
-
rnConDeclH98Details ::
Name
-> HsDocContext
=====================================
compiler/GHC/Tc/Gen/HsType.hs
=====================================
@@ -2144,9 +2144,8 @@ checkExpKind _rn_ty ty ki (Infer cell) = do
---------------------------
-tcHsContext :: Maybe (LHsContext GhcRn) -> TcM [PredType]
-tcHsContext Nothing = return []
-tcHsContext (Just cxt) = tc_hs_context typeLevelMode cxt
+tcHsContext :: Foldable t => t (LHsContext GhcRn) -> TcM [PredType]
+tcHsContext = foldMapM (tc_hs_context typeLevelMode)
tcLHsPredType :: LHsType GhcRn -> TcM PredType
tcLHsPredType pred = tc_lhs_pred typeLevelMode pred
=====================================
compiler/GHC/Tc/TyCl.hs
=====================================
@@ -2263,14 +2263,14 @@ kcConDecl new_or_data _tc_res_kind
(ConDeclGADT { con_names = names
, con_outer_bndrs = L _ outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = cxt
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = res_ty })
= -- See Note [kcConDecls: kind-checking data type decls]
addErrCtxt (DataConDefCtxt names) $
-- Not sure this is right, should just extend rather than skolemise but no test
bind_con_tvbs outer_bndrs inner_bndrs $
- do { _ <- tcHsContext cxt
+ do { _ <- tcHsContext cxts
; traceTc "kcConDecl:GADT {" (ppr names $$ ppr res_ty)
; con_res_kind <- newOpenTypeKind
; _ <- tcCheckLHsTypeInContext res_ty (TheKind con_res_kind)
@@ -4175,7 +4175,7 @@ tcConDecl new_or_data dd_info rep_tycon tc_bndrs _res_kind tag_map
(ConDeclGADT { con_names = names
, con_outer_bndrs = L _ outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = cxt, con_g_args = hs_args
+ , con_cxts = cxts, con_g_args = hs_args
, con_res_ty = hs_res_ty })
= addErrCtxt (DataConDefCtxt names) $
do { traceTc "tcConDecl 1 gadt" (ppr names)
@@ -4184,7 +4184,7 @@ tcConDecl new_or_data dd_info rep_tycon tc_bndrs _res_kind tag_map
; (tclvl, wanted, (tvbs, (ctxt, arg_tys, res_ty, field_lbls, stricts)))
<- pushLevelAndSolveEqualitiesX "tcConDecl:GADT" $
tcGadtConTyVarBndrs skol_info outer_bndrs inner_bndrs $
- do { ctxt <- tcHsContext cxt
+ do { ctxt <- tcHsContext cxts
; (res_ty, res_kind) <- tcInferLHsTypeKind hs_res_ty
-- See Note [GADT return kinds]
=====================================
compiler/GHC/ThToHs.hs
=====================================
@@ -59,7 +59,7 @@ import Data.Bifunctor (first)
import Data.Foldable (for_)
import Data.List.NonEmpty( NonEmpty (..), nonEmpty )
import qualified Data.List.NonEmpty as NE
-import Data.Maybe( catMaybes, isNothing )
+import Data.Maybe( catMaybes, maybeToList, isNothing )
import Data.Word (Word64)
import GHC.Boot.TH.Syntax as TH
import Foreign.ForeignPtr
@@ -718,16 +718,23 @@ cvtConstr parent_con do_con_name (ForallC tvs ctxt con)
add_cxt (L loc (HsContext _ cxt1)) (Just (L _ (HsContext _ cxt2)))
= Just (L loc (HsContext noAnn (cxt1 ++ cxt2)))
- -- Nested foralls end up flattened (see tests/th/GadtConSigs_th_dump1.stderr)
+ prepend_cxt :: LHsContext GhcPs -> [LHsContext GhcPs] -> [LHsContext GhcPs]
+ prepend_cxt lcxt = map_mb_head (add_cxt lcxt)
+ where
+ map_mb_head :: (Maybe a -> Maybe a) -> [a] -> [a]
+ map_mb_head f [] = maybeToList (f Nothing)
+ map_mb_head f (x:xs) = maybeToList (f (Just x)) ++ xs
+
+ -- Nested foralls and contexts end up flattened (see tests/th/GadtConSigs_th_dump1.stderr)
-- but it doesn't seem to matter.
add_forall :: [LHsTyVarBndr Hs.Specificity GhcPs] -> LHsContext GhcPs
-> ConDecl GhcPs -> ConDecl GhcPs
add_forall tvs' cxt' con@(ConDeclGADT { con_outer_bndrs = L l outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = cxt })
+ , con_cxts = cxts })
= con { con_outer_bndrs = L l outer_bndrs'
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = add_cxt cxt' cxt }
+ , con_cxts = prepend_cxt cxt' cxts }
where
outer_bndrs'
| null all_tvs = mkHsOuterImplicit
@@ -770,7 +777,7 @@ mk_gadt_decl names args res_ty
, con_names = names
, con_outer_bndrs = outer_bndrs
, con_inner_bndrs = []
- , con_mb_cxt = Nothing
+ , con_cxts = []
, con_g_args = args
, con_res_ty = res_ty
, con_modifiers = []
=====================================
compiler/Language/Haskell/Syntax/Decls.hs
=====================================
@@ -964,7 +964,7 @@ data ConDecl pass
, con_inner_bndrs :: [LHsGadtTelescope pass]
-- ^ The forall telescopes other than the outermost invisible forall,
-- interleaved with the parentheses that enclose them.
- , con_mb_cxt :: Maybe (LHsContext pass) -- ^ User-written context (if any)
+ , con_cxts :: [LHsContext pass] -- ^ User-written contexts
, con_g_args :: HsConDeclGADTDetails pass -- ^ Arguments; never infix
, con_res_ty :: LHsType pass -- ^ Result type
@@ -994,7 +994,7 @@ data ConDecl pass
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The types of both forms of GADT constructors are very structured, as they
must consist of the quantified type variables (if provided), followed by the
-context (if provided), followed by the argument types (if provided), followed
+contexts (if provided), followed by the argument types (if provided), followed
by the result type. (See "Wrinkle: No nested foralls or contexts" below for
more discussion on the restrictions imposed here.) As a result, instead of
storing the type of a GADT constructor as a single LHsType, we split it up
@@ -1069,6 +1069,8 @@ the GADT type, in precisely that order. For instance:
MkT2 :: forall a. Eq a => forall b. a -> b -> T
-- Rejected, `forall b` is nested
MkT3 :: forall a b. Eq a => Eq b => a -> b -> T
+ -- OK, `Eq a` and `Eq b` are consecutive
+ MkT3' :: forall a b. Eq a => a -> Eq b => b -> T
-- Rejected, `Eq b` is nested
MkT4 :: Int -> forall a. a -> T
-- Rejected, `forall a` is nested
@@ -1084,10 +1086,11 @@ User's Guide. GHC enforces that GADT constructors do not have nested `forall`s
or contexts in a single place:
GHC, in the process of splitting apart a GADT's type,
- extracts out the leading `forall`s and context (if they are provided). To
- accomplish this splitting, the parser uses the GHC.Hs.Type.splitLHsGadtTy
- function, which records the parentheses that surround the leading `forall`s
- in con_inner_bndrs (as these parentheses are syntactically significant).
+ extracts out the leading `forall`s and the adjacent contexts (if they are
+ provided). To accomplish this splitting, the parser uses the
+ GHC.Hs.Type.splitLHsGadtTy function, which records the parentheses that
+ surround the leading `forall`s in con_inner_bndrs (as these parentheses are
+ syntactically significant), and the contexts in con_cxts.
If the body returned by splitLHsGadtTy still contains any `forall`s or
contexts, then they must be nested, so they will be rejected.
=====================================
compiler/Language/Haskell/Syntax/Type.hs
=====================================
@@ -416,7 +416,7 @@ data HsGadtTelescope pass
= HsGadtForAll !(XGadtForAll pass) (HsForAllTelescope pass)
| HsGadtPar !(XGadtPar pass)
-- ^ `HsGadtPar` is only usefull for pretty-printing/exact-printing for recovering
- -- parenthisis interleaved with foralls.
+ -- parentheses interleaved with foralls.
--
-- This approach differs from `HsPar`, which wraps the inner expression as if
-- surrounding it with parentheses. We can ditch the `HsPar` approach because
=====================================
docs/users_guide/exts/gadt_syntax.rst
=====================================
@@ -124,7 +124,7 @@ grammar is subject to change in the future.
.. code-block:: none
- gadt_con ::= conids '::' foralls opt_ctxt gadt_body
+ gadt_con ::= conids '::' foralls ctxts gadt_body
conids ::= conid
| conid ',' conids
@@ -145,9 +145,9 @@ grammar is subject to change in the future.
| '{' tyvar '}'
| '{' tyvar '::' ctype '}'
- opt_ctxt ::= <empty>
- | btype '=>'
- | '(' ctxt ')' '=>'
+ ctxts ::= <empty>
+ | btype '=>'
+ | '(' ctxt ')' '=>'
ctxt ::= ctype
| ctype ',' ctxt
@@ -194,15 +194,29 @@ syntactically allowed. Some further various observations about this grammar:
- GADT constructor types are currently not permitted to have arbitrarily nested
``forall``\ s or ``=>``\ s. (e.g., something like ``MkT :: Int -> forall a. a -> T``
- would be rejected.) As a result, ``gadt_sig`` puts all of its quantification
- and constraints up front with ``foralls`` and ``opt_context``. Note that
+ would be rejected.) As a result, ``gadt_con`` puts all of its quantification
+ and constraints up front with ``foralls`` and ``ctxts``. Note that
higher-rank ``forall``\ s and ``=>``\ s are only permitted if they do not appear
directly to the right of a function arrow in a `prefix_gadt_body`. (e.g.,
something like ``MkS :: Int -> (forall a. a) -> S`` is allowed, since
parentheses separate the ``forall`` from the ``->``.)
+- A prefix GADT constructor may be given several consecutive contexts, as
+ indicated by `ctxts`. Curried contexts are equivalent to a single conjoined
+ context, so the following constructors have interchangeable types: ::
+
+ data G a where
+ MkCurried :: C a => D a => E a => G a
+ MkConjoined :: (C a, D a, E a) => G a
+ MkMixedL :: (C a, D a) => E a => G a
+ MkMixedR :: C a => (D a, E a) => G a
+
+ Note that, per the grammar above, the contexts must be consecutive: it is
+ currently not possible to interleave contexts with foralls or function arrows.
+ This restriction will be lifted in a future release of GHC.
+
- GADT constructors permit outermost parentheses that surround the ``foralls``
- or ``opt_ctxt``, as well as interleaved parentheses between multiple
+ or ``ctxts``, as well as interleaved parentheses between multiple
``foralls``. For example, ``MkU :: (forall a. a -> U)`` is accepted, as is
``MkW :: forall a. (forall b. a -> b -> W)``.
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -432,7 +432,7 @@ https://gitlab.haskell.org/ghc/ghc/-/merge_requests/16644, using
data InnerBindings
= InnerMore (LHsGadtTelescope GhcPs) InnerBindings
- | InnerDone (Maybe (LHsContext GhcPs), HsConDeclGADTDetails GhcPs, LHsType GhcPs)
+ | InnerDone ([LHsContext GhcPs], HsConDeclGADTDetails GhcPs, LHsType GhcPs)
The key part of the ExactPrint instance for this is
@@ -4146,6 +4146,14 @@ instance ExactPrint (HsType GhcPs) where
(ann', mt') <- exactBang (ann, mt) str
ty' <- markAnnotated ty
return (XHsType (HsBangTy ann' (HsSrcBang mt' up str) ty'))
+ -- mkGadtDecl sometimes leaves HsRecTy intact instead of converting
+ -- it to RecConGADT, counting on the renamer to reject it later on.
+ -- Exact printing must cope with it.
+ exact (XHsType (HsRecTy (o,c) flds)) = do
+ o' <- markEpToken o
+ flds' <- markAnnotated flds
+ c' <- markEpToken c
+ return (XHsType (HsRecTy (o',c') flds'))
exact (HsExplicitListTy (sq,o,c) prom tys) = do
sq' <- if (isPromoted prom)
then markEpToken sq
@@ -4462,7 +4470,7 @@ instance ExactPrint (ConDecl GhcPs) where
, con_names = cons
, con_outer_bndrs = outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt, con_g_args = args
+ , con_cxts = cxts, con_g_args = args
, con_modifiers = mods
, con_res_ty = res_ty, con_doc = doc }) = do
mods' <- mapM markAnnotated mods
@@ -4475,15 +4483,15 @@ instance ExactPrint (ConDecl GhcPs) where
L _ (HsOuterImplicit _) -> return outer_bndrs
_ -> markAnnotated outer_bndrs
- let ib = toInnerBindings inner_bndrs (mcxt, args, res_ty)
+ let ib = toInnerBindings inner_bndrs (cxts, args, res_ty)
ib' <- markAnnotated ib
- let (inner_bndrs', (mcxt', args', res_ty')) = fromInnerBindings ib'
+ let (inner_bndrs', (cxts', args', res_ty')) = fromInnerBindings ib'
return (ConDeclGADT { con_g_ext = AnnConDeclGADT [] [] dcol'
, con_names = cons'
, con_outer_bndrs = outer_bndrs'
, con_inner_bndrs = inner_bndrs'
- , con_mb_cxt = mcxt', con_g_args = args'
+ , con_cxts = cxts', con_g_args = args'
, con_modifiers = mods'
, con_res_ty = res_ty', con_doc = doc })
@@ -4491,14 +4499,14 @@ instance ExactPrint (ConDecl GhcPs) where
data InnerBindings
= InnerMore (LHsGadtTelescope GhcPs) InnerBindings
- | InnerDone (Maybe (LHsContext GhcPs), HsConDeclGADTDetails GhcPs, LHsType GhcPs)
+ | InnerDone ([LHsContext GhcPs], HsConDeclGADTDetails GhcPs, LHsType GhcPs)
toInnerBindings :: [LHsGadtTelescope GhcPs]
- -> (Maybe (LHsContext GhcPs), HsConDeclGADTDetails GhcPs, LHsType GhcPs) -> InnerBindings
+ -> ([LHsContext GhcPs], HsConDeclGADTDetails GhcPs, LHsType GhcPs) -> InnerBindings
toInnerBindings [] inner = InnerDone inner
toInnerBindings (b:bs) inner = InnerMore b (toInnerBindings bs inner)
-fromInnerBindings :: InnerBindings -> ([LHsGadtTelescope GhcPs], (Maybe (LHsContext GhcPs), HsConDeclGADTDetails GhcPs, LHsType GhcPs))
+fromInnerBindings :: InnerBindings -> ([LHsGadtTelescope GhcPs], ([LHsContext GhcPs], HsConDeclGADTDetails GhcPs, LHsType GhcPs))
fromInnerBindings = go []
where
go acc (InnerMore b n) = go (b:acc) n
@@ -4520,8 +4528,8 @@ instance ExactPrint InnerBindings where
xs' <- markAnnotated xs
rp' <- markEpToken rp
return (InnerMore (L l (HsGadtPar (lp',rp'))) xs')
- exact (InnerDone (mcxt, args, res_ty)) = do
- mcxt' <- markAnnotated mcxt
+ exact (InnerDone (cxts, args, res_ty)) = do
+ cxts' <- mapM markAnnotated cxts
args' <-
case args of
(PrefixConGADT x args0) -> do
@@ -4534,7 +4542,7 @@ instance ExactPrint InnerBindings where
rarr' <- markEpUniToken rarr
return (RecConGADT (oc',cc',rarr') fields')
res_ty' <- markAnnotated res_ty
- return (InnerDone (mcxt', args', res_ty'))
+ return (InnerDone (cxts', args', res_ty'))
-- ---------------------------------------------------------------------
=====================================
utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
=====================================
@@ -340,7 +340,7 @@ ppCtor
{ con_names = names
, con_outer_bndrs = L _ outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = res_ty
}
@@ -352,9 +352,7 @@ ppCtor
con_sig_ty = HsSig noExtField outer_bndrs $
mkGadtArgTys inner_bndrs phi_ty
where
- phi_ty = case mcxt of
- Just theta -> mkQualTy theta tau_ty
- Nothing -> tau_ty
+ phi_ty = foldr mkQualTy tau_ty cxts
tau_ty = foldr mkFunTy res_ty $
case args of
PrefixConGADT _ pos_args -> map cdf_type pos_args
=====================================
utils/haddock/haddock-api/src/Haddock/Convert.hs
=====================================
@@ -29,7 +29,7 @@ module Haddock.Convert
import Control.DeepSeq (force)
import Data.Either (lefts, partitionEithers, rights)
-import Data.Maybe (catMaybes, mapMaybe)
+import Data.Maybe (catMaybes, mapMaybe, maybeToList)
import GHC.Builtin.KnownKeys
( boxedRepDataConKey
, eqTyConKey
@@ -625,7 +625,7 @@ synifyDataCon use_gadt_syntax dc =
, con_names = pure name
, con_outer_bndrs = noLocA outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = ctx
+ , con_cxts = maybeToList ctx
, con_g_args = hat
, con_res_ty = synifyType WithinType emptyVarSet res_ty
, con_modifiers = []
=====================================
utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
=====================================
@@ -220,7 +220,7 @@ getGADTConType
( ConDeclGADT
{ con_outer_bndrs = outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = mcxt
+ , con_cxts = cxts
, con_g_args = args
, con_res_ty = res_ty
}
@@ -234,9 +234,7 @@ getGADTConType
)
where
phi_ty :: LHsType DocNameI
- phi_ty = case mcxt of
- Nothing -> tau_ty
- Just theta -> mkQualTy theta tau_ty
+ phi_ty = foldr mkQualTy tau_ty cxts
tau_ty :: LHsType DocNameI
tau_ty = case args of
=====================================
utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
=====================================
@@ -758,7 +758,7 @@ renameCon
{ con_names = lnames
, con_outer_bndrs = outer_bndrs
, con_inner_bndrs = inner_bndrs
- , con_mb_cxt = lcontext
+ , con_cxts = lcontexts
, con_g_args = details
, con_res_ty = res_ty
, con_modifiers = mods
@@ -767,7 +767,7 @@ renameCon
lnames' <- mapM renameNameL lnames
outer_bndrs' <- mapM renameOuterTyVarBndrs outer_bndrs
inner_bndrs' <- mapM renameHsGadtTelescope inner_bndrs
- lcontext' <- traverse renameLContext lcontext
+ lcontexts' <- traverse renameLContext lcontexts
details' <- renameGADTDetails details
res_ty' <- renameLType res_ty
mods' <- renameModifiers mods
@@ -778,7 +778,7 @@ renameCon
, con_names = lnames'
, con_outer_bndrs = outer_bndrs'
, con_inner_bndrs = inner_bndrs'
- , con_mb_cxt = lcontext'
+ , con_cxts = lcontexts'
, con_g_args = details'
, con_res_ty = res_ty'
, con_modifiers = mods'
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bb2c9f3555bfd5d3ce16eafecd21328…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bb2c9f3555bfd5d3ce16eafecd21328…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
8ddbc6f9 by Florian Ragwitz at 2026-10-14T13:49:28-04:00
Remove obsolete HPC types
Fixes #27946.
- - - - -
6 changed files:
- + changelog.d/hpc-cleanup
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/CoreToStg.hs
- compiler/GHC/StgToJS/ExprCtx.hs
- compiler/GHC/Types/Id/Info.hs
Changes:
=====================================
changelog.d/hpc-cleanup
=====================================
@@ -0,0 +1,8 @@
+synopsis: Remove ``TickBoxOpId`` constructor of ``IdDetails`` and related dead code
+section: ghc-lib
+issues: #27946
+mrs: !16816
+description:
+ The obsolete ``TickBoxOpId`` constructor of ``GHC.Types.Id.Info.IdDetails``,
+ along with the associated types ``TickBoxOp`` and ``TickBoxId`` have been
+ removed.
=====================================
compiler/GHC/Core/Opt/Specialise.hs
=====================================
@@ -1867,7 +1867,7 @@ the specialised Id correct:
allows unboxing of all previous CBV args, in which case sticking to
VanillaIds was the only correct choice to begin with.
-* RecSelId, DataCon*Id, ClassOpId, PrimOpId, FCallId, CoVarId, TickBoxId:
+* RecSelId, DataCon*Id, ClassOpId, PrimOpId, FCallId, CoVarId:
Never specialised.
Note [Specialisation Must Preserve Sharing]
@@ -3074,7 +3074,6 @@ wantCallsFor _env f
ClassOpId {} -> False
PrimOpId {} -> False
FCallId {} -> False
- TickBoxOpId {} -> False
CoVarId {} -> False
DFunId {} -> True
=====================================
compiler/GHC/CoreToIface.hs
=====================================
@@ -492,7 +492,6 @@ toIfaceIdDetails _ (RepPolyId {}) = IfVanillaId
toIfaceIdDetails nm dets@(DataConWorkId {}) = not_iface_details nm dets
toIfaceIdDetails nm dets@(DataConWrapId {}) = not_iface_details nm dets
toIfaceIdDetails nm dets@(FCallId {}) = not_iface_details nm dets
-toIfaceIdDetails nm dets@(TickBoxOpId {}) = not_iface_details nm dets
toIfaceIdDetails nm dets@(CoVarId {}) = not_iface_details nm dets
toIfaceIdDetails nm dets@(JoinId {}) = not_iface_details nm dets
=====================================
compiler/GHC/CoreToStg.hs
=====================================
@@ -587,8 +587,6 @@ mkStgApp f how_bound core_args stg_args res_ty
FCallId call -> assert exactly_saturated $
StgOpApp (StgFCallOp call (idType f)) stg_args res_ty
- TickBoxOpId {} -> pprPanic "coreToStg TickBox" $ ppr (f,stg_args)
-
_other -> StgApp f stg_args
where
-- Mostly, the arity info of a function is in the fn's IdInfo
=====================================
compiler/GHC/StgToJS/ExprCtx.hs
=====================================
@@ -163,9 +163,6 @@ ctxIsEvaluated i =
-- JoinId {} -> False
-- -- Don't speculate join points
- -- TickBoxOpId {} -> False
- -- -- Don't speculate box ticking
-
-- -- Tagged (evaluated) ids
-- _ | Just sig <- idTagSig_maybe i
-- , isTaggedSig sig
=====================================
compiler/GHC/Types/Id/Info.hs
=====================================
@@ -83,9 +83,6 @@ module GHC.Types.Id.Info (
lfInfo, setLFInfo, setTagSig,
tagSig,
-
- -- ** Tick-box Info
- TickBoxOp(..), TickBoxId,
) where
import GHC.Prelude
@@ -102,7 +99,6 @@ import GHC.Core.Type (mkTyConApp)
import GHC.Core.PatSyn
import GHC.Core.ConLike
import GHC.Types.ForeignCall
-import GHC.Unit.Module
import GHC.Types.Demand
import GHC.Types.Cpr
import GHC.Types.InlinePragma
@@ -195,8 +191,6 @@ data IdDetails
| FCallId ForeignCall -- ^ The 'Id' is for a foreign call.
-- Type will be simple: no type families, newtypes, etc
- | TickBoxOpId TickBoxOp -- ^ The 'Id' is for a HPC tick box (both traditional and binary)
-
| DFunId Bool -- ^ A dictionary function.
-- Bool = True <=> a dictionary of this class cannot be bottom
-- See Note [NON-BOTTOM-DICTS invariant] in GHC.Core
@@ -445,7 +439,6 @@ pprIdDetails other = brackets (pp other)
pp (RepPolyId {}) = text "RepPolyId"
pp (PrimOpId {}) = text "PrimOp"
pp (FCallId _) = text "ForeignCall"
- pp (TickBoxOpId _) = text "TickBoxOp"
pp (DFunId terminating) = text "DFunId"
<> ppWhen (not terminating) (text "(may-be-bottom)")
pp (RecSelId { sel_naughty = is_naughty })
@@ -970,20 +963,3 @@ zapTailCallInfo info
zapCallArityInfo :: IdInfo -> IdInfo
zapCallArityInfo info = setCallArityInfo info 0
-
-{-
-************************************************************************
-* *
-\subsection{TickBoxOp}
-* *
-************************************************************************
--}
-
-type TickBoxId = Int
-
--- | Tick box for Hpc-style coverage
-data TickBoxOp
- = TickBox Module {-# UNPACK #-} !TickBoxId
-
-instance Outputable TickBoxOp where
- ppr (TickBox mod n) = text "tick" <+> ppr (mod,n)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8ddbc6f9b378f1547fb758566ccdc61…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8ddbc6f9b378f1547fb758566ccdc61…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][master] Fix #27836, normalise unit database path in ExternalUnitDatabases
by Marge Bot (@marge-bot) 14 Oct '26
by Marge Bot (@marge-bot) 14 Oct '26
14 Oct '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
3a72b8a2 by Hannes Siebenhandl at 2026-10-14T13:48:32-04:00
Fix #27836, normalise unit database path in ExternalUnitDatabases
Add a regression test, proofing that all variations:
- local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf
- ./local-unit-db/my-test.conf/
are parsed only once.
- - - - -
12 changed files:
- changelog.d/unit-index
- compiler/GHC/Data/OsPath.hs
- compiler/GHC/Unit/External/Database.hs
- + testsuite/tests/driver/T27836/A.hs
- + testsuite/tests/driver/T27836/B.hs
- + testsuite/tests/driver/T27836/C.hs
- + testsuite/tests/driver/T27836/Makefile
- + testsuite/tests/driver/T27836/T27836.stdout
- + testsuite/tests/driver/T27836/all.T
- + testsuite/tests/driver/T27836/unitA
- + testsuite/tests/driver/T27836/unitB
- + testsuite/tests/driver/T27836/unitC
Changes:
=====================================
changelog.d/unit-index
=====================================
@@ -1,7 +1,7 @@
section: compiler
-synopsis: Use global ``UnitIndex`` to deduplicate ``UnitInfo``\s over multiple home units
-issues: #27500 #26423 #27748 #27834 #27835
-mrs: !16115 !16598 !16743 !16748
+synopsis: Use global ``UnitIndex`` to deduplicate ``UnitInfo``s over multiple home units
+issues: #27500 #26423 #27748 #27834 #27835 #27836
+mrs: !16115 !16598 !16743 !16748 !16729
description: {
The ``UnitState`` used to be duplicated for all ``HomeUnitEnv``, not sharing any of the ``UnitInfo``\s.
=====================================
compiler/GHC/Data/OsPath.hs
=====================================
@@ -13,6 +13,7 @@ module GHC.Data.OsPath
, (<.>)
, splitSearchPath
, isRelative
+ , normalise
, dropTrailingPathSeparator
, takeDirectory
, isSuffixOf
=====================================
compiler/GHC/Unit/External/Database.hs
=====================================
@@ -53,9 +53,17 @@ import System.FilePath as FilePath
-- ExternalUnitDatabases
-- ----------------------------------------------------------------------------
+-- | A normalised 'OsPath' that we use as the key to cache 'UnitDatabase's.
+--
+-- Removes trailing path separators and unit database paths starting with @./@.
+newtype NormalisedUnitDbLoc = NormalisedUnitDbLoc OsPath
+ deriving (Eq, Ord)
+
-- | Caches unit databases in-memory.
data ExternalUnitDatabases unit = ExternalUnitDatabases
- { eud_cachedDatabases :: !(Map OsPath (UnitDatabase unit))
+ { eud_cachedDatabases :: !(Map NormalisedUnitDbLoc (UnitDatabase unit))
+ -- ^ The 'Map' is keyed by a normalised 'OsPath', ensuring that 'lookupExternalUnitDatabases'
+ -- will never get confused by a stray @./@ or trailing @/@.
}
emptyExternalUnitDatabases :: ExternalUnitDatabases unit
@@ -67,18 +75,20 @@ emptyExternalUnitDatabases =
insertExternalUnitDatabases :: UnitDatabase unit -> ExternalUnitDatabases unit -> ExternalUnitDatabases unit
insertExternalUnitDatabases unit_db eud =
ExternalUnitDatabases
- { eud_cachedDatabases = Map.insert (unitDatabasePath unit_db) unit_db (eud_cachedDatabases eud)
+ { eud_cachedDatabases =
+ Map.insert (normalisedUnitDatabaseKey unit_db) unit_db (eud_cachedDatabases eud)
}
deleteExternalUnitDatabases :: OsPath -> ExternalUnitDatabases unit -> ExternalUnitDatabases unit
deleteExternalUnitDatabases unit_db_path eud =
ExternalUnitDatabases
- { eud_cachedDatabases = Map.delete unit_db_path (eud_cachedDatabases eud)
+ { eud_cachedDatabases =
+ Map.delete (normalisedUnitDatabaseKeyOsPath unit_db_path) (eud_cachedDatabases eud)
}
lookupExternalUnitDatabases :: OsPath -> ExternalUnitDatabases unit -> Maybe (UnitDatabase unit)
lookupExternalUnitDatabases key eud =
- Map.lookup key (eud_cachedDatabases eud)
+ Map.lookup (normalisedUnitDatabaseKeyOsPath key) (eud_cachedDatabases eud)
-- ----------------------------------------------------------------------------
-- UnitDatabase
@@ -87,12 +97,38 @@ lookupExternalUnitDatabases key eud =
-- | Unit database entry.
data UnitDatabase unit = UnitDatabase
{ unitDatabasePath :: OsPath
+ -- ^ On-disk location of the unit database.
+ --
, unitDatabaseUnits :: [GenUnitInfo unit]
+ -- ^ Units read from the database located at 'unitDatabasePath'.
+ --
+ -- These units have the @$pkgroot@ variable already resolved.
}
instance (Outputable u) => Outputable (UnitDatabase u) where
ppr (UnitDatabase fp _u) = text "DB:" <+> ppr fp
+normalisedUnitDatabaseKey :: UnitDatabase unit -> NormalisedUnitDbLoc
+normalisedUnitDatabaseKey unit_db = normalisedUnitDatabaseKeyOsPath $ unitDatabasePath unit_db
+
+-- | Normalise the unit database location and drop trailing path separators.
+--
+-- This ensures that two databases that point to the same location can be cached.
+--
+-- We need to remove trailing slash from the 'OsPath' before calculating @$pkgroot@ (Fix #16360)
+normalisedUnitDatabaseKeyOsPath :: OsPath -> NormalisedUnitDbLoc
+normalisedUnitDatabaseKeyOsPath db_path =
+ NormalisedUnitDbLoc $ OsPath.dropTrailingPathSeparator $ OsPath.normalise db_path
+
+-- | Get the root location of a unit database.
+-- Used to replace @$pkgroot@ variables in the 'GenericUnitInfo'.
+unitDatabaseRoot :: OsPath -> OsPath
+unitDatabaseRoot p =
+ let
+ NormalisedUnitDbLoc np = normalisedUnitDatabaseKeyOsPath p
+ in
+ OsPath.takeDirectory np
+
-- ----------------------------------------------------------------------------
--
-- Merging databases
@@ -258,14 +294,12 @@ readUnitDatabase logger cfg conf_file = do
"can't find a package database at " ++ show conf_file
let
- -- Fix #16360: remove trailing slash from conf_file before calculating pkgroot
- conf_file' = OsPath.dropTrailingPathSeparator conf_file
top_dir = OsPath.unsafeEncodeUtf (unitDbConfigGHCDir cfg)
- pkgroot = OsPath.takeDirectory conf_file'
+ pkgroot = unitDatabaseRoot conf_file
pkg_configs1 = map (mungeUnitInfo top_dir pkgroot . mapUnitInfo (\(UnitKey x) -> UnitId x) . mkUnitKeyInfo)
proto_pkg_configs
--
- return $ UnitDatabase conf_file' pkg_configs1
+ return $ UnitDatabase conf_file pkg_configs1
where
readDirStyleUnitInfo :: OsPath -> IO [DbUnitInfo]
readDirStyleUnitInfo conf_dir = do
=====================================
testsuite/tests/driver/T27836/A.hs
=====================================
@@ -0,0 +1,4 @@
+module A where
+
+a :: Int
+a = 1
=====================================
testsuite/tests/driver/T27836/B.hs
=====================================
@@ -0,0 +1,4 @@
+module B where
+
+b :: Int
+b = 1
=====================================
testsuite/tests/driver/T27836/C.hs
=====================================
@@ -0,0 +1,4 @@
+module C where
+
+b :: Int
+b = 1
=====================================
testsuite/tests/driver/T27836/Makefile
=====================================
@@ -0,0 +1,21 @@
+TOP=../../..
+include $(TOP)/mk/boilerplate.mk
+include $(TOP)/mk/test.mk
+
+T27836:
+ mkdir local-unit-db/
+ cd local-unit-db/ && '$(GHC_PKG)' init my-test.conf
+ # All these unit database paths should resolve to the same location
+ # thus after the first time parsing the unit database, we shouldn't parse it again.
+ '$(TEST_HC)' $(TEST_HC_OPTS) --make \
+ -unit @unitA -unit @unitB -unit @unitC \
+ -v2 -fforce-recomp 2>&1 \
+ | grep 'Using binary package database:'
+
+ echo ""
+ echo ""
+ echo "All -package-db variations:"
+ echo "- local-unit-db/my-test.conf"
+ echo "- ./local-unit-db/my-test.conf"
+ echo "- ./local-unit-db/my-test.conf/"
+ echo "Must be parsed only once."
=====================================
testsuite/tests/driver/T27836/T27836.stdout
=====================================
@@ -0,0 +1,8 @@
+Using binary package database: local-unit-db/my-test.conf/package.cache
+
+
+All -package-db variations:
+- local-unit-db/my-test.conf
+- ./local-unit-db/my-test.conf
+- ./local-unit-db/my-test.conf/
+Must be parsed only once.
=====================================
testsuite/tests/driver/T27836/all.T
=====================================
@@ -0,0 +1,4 @@
+test('T27836',
+ [ extra_files(['A.hs', 'B.hs', 'C.hs', 'unitA', 'unitB', 'unitC']), normalise_slashes
+ ],
+ makefile_test, ['T27836'])
=====================================
testsuite/tests/driver/T27836/unitA
=====================================
@@ -0,0 +1 @@
+-hide-all-packages -no-user-package-db -package-db local-unit-db/my-test.conf -package base -this-unit-id a-0.0.0 A
=====================================
testsuite/tests/driver/T27836/unitB
=====================================
@@ -0,0 +1 @@
+-hide-all-packages -no-user-package-db -package-db ./local-unit-db/my-test.conf -package base -this-unit-id b-0.0.0 B
=====================================
testsuite/tests/driver/T27836/unitC
=====================================
@@ -0,0 +1 @@
+-hide-all-packages -no-user-package-db -package-db ./local-unit-db/my-test.conf/ -package base -this-unit-id c-0.0.0 C
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3a72b8a28a281008d6904210107b95c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3a72b8a28a281008d6904210107b95c…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0