Haskell.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

ghc-commits

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
ghc-commits@haskell.org

August 2026

  • 1 participants
  • 637 discussions
[Git][ghc/ghc][wip/jeltsch/textual-bytecode-output] Add tracing to find out the suffix for `emsdk` tests
by Wolfgang Jeltsch (@jeltsch) 06 Aug '26

06 Aug '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/textual-bytecode-output at Glasgow Haskell Compiler / GHC Commits: 4c9c91ab by Wolfgang Jeltsch at 2026-08-06T14:53:28+03:00 Add tracing to find out the suffix for `emsdk` tests - - - - - 1 changed file: - testsuite/driver/testlib.py Changes: ===================================== testsuite/driver/testlib.py ===================================== @@ -3486,6 +3486,9 @@ def find_expected_file(name: TestName, suff: str, way: WayName) -> Path: for ws in ['-ws-' + config.wordsize, ''] for way_ext in ['-' + way, '']] + if name == 'show-bytestring-vanilla': + print(files) + for f in files: if in_srcdir(f).exists(): return f View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4c9c91ab887a5e2f216f8a010aa2078… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4c9c91ab887a5e2f216f8a010aa2078… 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
0 0
[Git][ghc/ghc][wip/T27557] Fix three bugs related to required type args and INLINE pragmas
by Simon Peyton Jones (@simonpj) 06 Aug '26

06 Aug '26
Simon Peyton Jones pushed to branch wip/T27557 at Glasgow Haskell Compiler / GHC Commits: d373dba2 by Simon Peyton Jones at 2026-08-06T12:47:21+01:00 Fix three bugs related to required type args and INLINE pragmas * `GHC.Core.Opt.Arity.mkEtaForAllMCo` got the visibility flags back to front, leading to a Lint error (#27557) * The arity in an InlineSaturation is the VisArity not the Arity; the two can differ when we have "required" type arguments. This made the INLINE pragma argument counting go wrong in `makeCorePair` (#27590). * When a simple binding has a type signature, we take special path in `tcPolyCheck`, leading to an outer `AbsBinds` that has no dictionaries, even when the binding is in fact overloaded. That confused the inline-arity computation in `makeCorePair` (#27589). The latter two are fixed using the new function `GHC.HsToCore.Binds.findSatArity`. That actually simplifies the API of `makeCorePair`, which is nice. The first bug is fixed by swapping the visiblity flags in `GHC.Core.Opt.Arity.mkEtaForAllMCo` Getting the INLINE behaviour right led to some perf changes: * Runtime /halved/ on T7954 due to better specialisation * Compile time increased by 6% in T21839c because a bit more inlining happened, as it always should have done. * For some reason compile-time max-bytes-used dropped by 30% on T27336, but only on one build configuration; and it increased on LinkableUsage02 by 6% on another configuration Geometric mean effect on our compile time benchmarks is +0.1%. Metric Decrease: T27336 T7954 Metric Increase: LinkableUsage02 T21839c - - - - - 21 changed files: - + changelog.d/T27557 - + changelog.d/T27589 - compiler/GHC/Core/Opt/Arity.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/HsToCore/Binds.hs - compiler/GHC/HsToCore/Match.hs - compiler/GHC/HsToCore/Ticks.hs - compiler/GHC/Tc/Gen/Bind.hs - compiler/GHC/Tc/Gen/Sig.hs - compiler/GHC/Types/Arity.hs - compiler/GHC/Types/InlinePragma.hs - compiler/GHC/Types/Var.hs - libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr - libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr - + testsuite/tests/simplCore/should_compile/T27589.hs - + testsuite/tests/simplCore/should_compile/T27589.stderr - + testsuite/tests/simplCore/should_compile/T27590.hs - + testsuite/tests/simplCore/should_compile/T27590.stderr - testsuite/tests/simplCore/should_compile/all.T - + testsuite/tests/typecheck/should_compile/T27557.hs - testsuite/tests/typecheck/should_compile/all.T Changes: ===================================== changelog.d/T27557 ===================================== @@ -0,0 +1,8 @@ +section: compiler +issues: #27577 +mrs: !16433 +synopsis: + Fix a Core Lint error involving RequiredTypeArguments +description: + Fixes an issue with a coercion being used for eta expansion storing + the wrong visibility information, which caused a Core Lint error. ===================================== changelog.d/T27589 ===================================== @@ -0,0 +1,10 @@ +section: compiler +issues: #27589 #27590 +mrs: !16433 +synopsis: + Fixes to arity computations +description: + The arity computation for INLINE pragmas now correctly takes into + account required type arguments. Separately, the arity computation + in ``tcPolyCheck`` now consistently handles dictionary arguments, fixing + a short-cut codepath which didn't ===================================== compiler/GHC/Core/Opt/Arity.hs ===================================== @@ -2370,11 +2370,15 @@ mkEtaForAllMCo (Bndr tcv vis) ty mco | otherwise -> mk_fco (mkRepReflCo ty) MCo co -> mk_fco co where - mk_fco co = MCo (mkForAllCo tcv vis coreTyLamForAllTyFlag MRefl co) + mk_fco co = MCo (mkForAllCo tcv coreTyLamForAllTyFlag vis MRefl co) -- coreTyLamForAllTyFlag: See Note [The EtaInfo mechanism], particularly -- the (EtaInfo Invariant). (sym co) wraps a lambda that always has -- a ForAllTyFlag of coreTyLamForAllTyFlag; see Note [Required foralls in Core] -- in GHC.Core.TyCo.Rep + -- + -- Orientation: remember, the output of mkEtaForAllCo goes into an `EI bs mco`, + -- and is SymCo'd in `etaInfoAbs`. Hence the orientation of the visibility + -- flags. A bit of a brain-strain (#27557). {- ************************************************************************ ===================================== compiler/GHC/Hs/Expr.hs ===================================== @@ -1687,10 +1687,11 @@ isSingletonMatchGroup matches | otherwise = False -matchGroupArity :: MatchGroup (GhcPass id) body -> Arity +matchGroupVisArity :: MatchGroup (GhcPass id) body -> VisArity -- This is called before type checking, when mg_arg_tys is not set -matchGroupArity MG { mg_alts = L _ [] } = 1 -- See Note [Empty mg_alts] -matchGroupArity MG { mg_alts = L _ (alt1 : _) } = count isVisArgLPat (hsLMatchPats alt1) +-- Returns the "visible arity" of the MatchGroup i.e. including required type arguments. +matchGroupVisArity MG { mg_alts = L _ [] } = 1 -- See Note [Empty mg_alts] +matchGroupVisArity MG { mg_alts = L _ (alt1 : _) } = count isVisArgLPat (hsLMatchPats alt1) hsLMatchPats :: LMatch (GhcPass id) body -> [LPat (GhcPass id)] hsLMatchPats (L _ (Match { m_pats = L _ pats })) = pats ===================================== compiler/GHC/HsToCore/Binds.hs ===================================== @@ -69,7 +69,7 @@ import GHC.Types.InlinePragma import GHC.Types.Name import GHC.Types.Var.Set import GHC.Types.Var.Env -import GHC.Types.Var( EvVar, mkLocalVar ) +import GHC.Types.Var( EvVar, mkLocalVar, isRuntimePiTyBinder ) import GHC.Types.SrcLoc import GHC.Types.Basic import GHC.Types.Unique.Set( nonDetEltsUniqSet ) @@ -196,7 +196,7 @@ dsHsBind dflags (VarBind { var_id = var = do { core_expr <- dsLExpr expr -- Dictionary bindings are always VarBinds, -- so we only need do this here - ; let core_bind@(id,_) = makeCorePair dflags var False 0 core_expr + ; let core_bind@(id,_) = makeCorePair dflags var False core_expr force_var = if xopt LangExt.Strict dflags then [id] else [] @@ -211,11 +211,11 @@ dsHsBind dflags b@(FunBind { fun_id = L loc fun ; let body' = mkOptTickBox tick body rhs = core_wrap (mkLams args body') - core_binds@(id,_) = makeCorePair dflags fun False 0 rhs + core_binds@(id,_) = makeCorePair dflags fun False rhs force_var -- Bindings are strict when -XStrict is enabled | xopt LangExt.Strict dflags - , matchGroupArity matches == 0 -- no need to force lambdas + , matchGroupVisArity matches == 0 -- no need to force lambdas = [id] | isBangedHsBind b = [id] @@ -303,7 +303,7 @@ dsAbsBinds dflags tyvars dicts exports ; let global_id' = addIdSpecialisations global_id rules main_bind = makeCorePair dflags global_id' (isDefaultMethod prags) - (dictArity dicts) rhs + rhs ; return (force_vars', fromOL spec_binds ++ [main_bind]) } } @@ -386,7 +386,7 @@ dsAbsBinds dflags tyvars dicts exports mk_aux_bind (lcl_id, rhs) = let lcl_w_inline = lookupVarEnv inline_env lcl_id `orElse` lcl_id in - makeCorePair dflags lcl_w_inline False 0 rhs + makeCorePair dflags lcl_w_inline False rhs inline_env :: IdEnv Id -- Maps a monomorphic local Id to one with -- the inline pragma from the source @@ -437,9 +437,9 @@ dsAbsBinds dflags tyvars dicts exports -- the unfolding in the interface file is made in `GHC.Iface.Tidy.addExternal` -- using this information. ------------------------ -makeCorePair :: DynFlags -> Id -> Bool -> Arity -> CoreExpr +makeCorePair :: DynFlags -> Id -> Bool -> CoreExpr -> (Id, CoreExpr) -makeCorePair dflags gbl_id is_default_method dict_arity rhs +makeCorePair dflags gbl_id is_default_method rhs | is_default_method -- Default methods are *always* inlined -- See Note [INLINE and default methods] in GHC.Tc.TyCl.Instance = (gbl_id `setIdUnfolding` mkCompulsoryUnfolding' simpl_opts rhs, rhs) @@ -456,22 +456,43 @@ makeCorePair dflags gbl_id is_default_method dict_arity rhs inline_prag = idInlinePragma gbl_id inlinable_unf = mkInlinableUnfolding simpl_opts StableUserSrc rhs inline_pair - | AppliedToAtLeast arity <- inlinePragmaSaturation inline_prag + | AppliedToAtLeast vis_arity <- inlinePragmaSaturation inline_prag -- Add an Unfolding for an INLINE (but not for NOINLINE) -- And eta-expand the RHS; see Note [Eta-expanding INLINE things] - , let real_arity = dict_arity + arity - -- NB: The arity passed to mkInlineUnfoldingWithArity - -- must take account of the dictionaries - = ( gbl_id `setIdUnfolding` mkInlineUnfoldingWithArity simpl_opts StableUserSrc real_arity rhs - , etaExpand real_arity rhs) + , let runtime_arity = findSatArity vis_arity (idType gbl_id) + -- NB: runtime_arity: the arity passed to mkInlineUnfoldingWithArity + -- must take account of dictionaries and required type args + = ( gbl_id `setIdUnfolding` mkInlineUnfoldingWithArity simpl_opts StableUserSrc + runtime_arity rhs + , etaExpand runtime_arity rhs) | otherwise = pprTrace "makeCorePair: arity missing" (ppr gbl_id) $ (gbl_id `setIdUnfolding` mkInlineUnfoldingNoArity simpl_opts StableUserSrc rhs, rhs) -dictArity :: [Var] -> Arity --- Don't count coercion variables in arity -dictArity dicts = count isId dicts +findSatArity :: VisArity -> Type -> Arity +-- Given the VisArity, find the value Arity of the function. +-- This is the number of runtime-value arguments the function must be applied +-- to before the INLINE pragma fires and inlines the function +-- We must: +-- add one for each invisible dictionary arg; and +-- subtract one for each required type argment +findSatArity vis_arity ty + = go vis_arity pi_bndrs + where + (pi_bndrs, _) = splitPiTys ty + + go vis_arity (bndr : bndrs) + | isInvisiblePiTyBinder bndr = add_bndr bndr (go vis_arity bndrs) + | vis_arity == 0 = 0 + | otherwise = add_bndr bndr (go (vis_arity-1) bndrs) + go vis_arity [] + | vis_arity == 0 = 0 + | otherwise = pprPanic "findSatArity" (ppr vis_arity $$ ppr ty) + + add_bndr :: PiTyBinder -> Arity -> Arity + add_bndr bndr ar | isRuntimePiTyBinder bndr = ar+1 + | otherwise = ar {- Note [Desugaring AbsBinds] ===================================== compiler/GHC/HsToCore/Match.hs ===================================== @@ -737,21 +737,21 @@ Call @match@ with all of this information! -- There are three possible cases for matchWrapper's scrutinees argument: -- -- 1. Nothing Used for FunBind, HsLam, HsLamcase, where there is no explicit scrutinee --- The MatchGroup may have matchGroupArity of 0 or more. Examples: --- f p1 q1 = ... -- matchGroupArity 2 +-- The MatchGroup may have matchGroupVisArity of 0 or more. Examples: +-- f p1 q1 = ... -- matchGroupVisArity 2 -- f p2 q2 = ... -- -- \cases | g1 -> ... -- matchGroupArity 0 -- | g2 -> ... -- -- 2. Just [e] Used for HsCase, RecordUpd; exactly one scrutinee --- The MatchGroup has matchGroupArity of exactly 1. Example: --- case e of p1 -> e1 -- matchGroupArity 1 +-- The MatchGroup has matchGroupVisArity of exactly 1. Example: +-- case e of p1 -> e1 -- matchGroupVisArity 1 -- p2 -> e2 -- -- 3. Just es Used for HsCmdLamCase; zero or more scrutinees -- The MatchGroup has matchGroupArity of (length es). Example: --- \cases p1 q1 -> returnA -< ... -- matchGroupArity 2 +-- \cases p1 q1 -> returnA -< ... -- matchGroupVisArity 2 -- p2 q2 -> ... matchWrapper ===================================== compiler/GHC/HsToCore/Ticks.hs ===================================== @@ -288,7 +288,7 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches -- We don't want to generate code for blacklisted positions -- We don't want redundant ticks on simple pattern bindings -- We don't want to tick non-exported bindings in TickExportedFunctions - let simple = matchGroupArity matches == 0 + let simple = matchGroupVisArity matches == 0 -- A binding is a "simple pattern binding" if it is a -- funbind with zero patterns toplev = null decl_path ===================================== compiler/GHC/Tc/Gen/Bind.hs ===================================== @@ -808,7 +808,7 @@ checkMonomorphismRestriction mbis lbinds restricted (VarBind { var_ext = x }) = dataConCantHappen x restricted b@(PatSynBind {}) = pprPanic "isRestrictedGroup/unrestricted" (ppr b) - restricted_match mg = matchGroupArity mg == 0 + restricted_match mg = matchGroupVisArity mg == 0 -- No args => like a pattern binding -- Some args => a function binding ===================================== compiler/GHC/Tc/Gen/Sig.hs ===================================== @@ -599,26 +599,26 @@ mkPragEnv sigs binds Nothing -> sig -- See Note [Pattern synonym inline arity] -- ar_env maps a local to the arity of its definition - ar_env :: NameEnv Arity - ar_env = foldr lhsBindArity emptyNameEnv binds + ar_env :: NameEnv VisArity + ar_env = foldr lhsBindVisArity emptyNameEnv binds -addInlinePragArity :: Arity -> LSig GhcRn -> LSig GhcRn +addInlinePragArity :: VisArity -> LSig GhcRn -> LSig GhcRn addInlinePragArity ar (L l (InlineSig x nm inl)) = L l (InlineSig x nm (add_inl_arity ar inl)) addInlinePragArity ar (L l (SpecSig x nm ty inl)) = L l (SpecSig x nm ty (add_inl_arity ar inl)) addInlinePragArity ar (L l (SpecSigE n x e inl)) = L l (SpecSigE n x e (add_inl_arity ar inl)) addInlinePragArity _ sig = sig -add_inl_arity :: Arity -> InlinePragma GhcRn -> InlinePragma GhcRn +add_inl_arity :: VisArity -> InlinePragma GhcRn -> InlinePragma GhcRn add_inl_arity ar prag@(InlinePragma { inl_inline = inl_spec }) | Inline {} <- inl_spec -- Add arity only for real INLINE pragmas, not INLINABLE = prag `setInlinePragmaSaturation` AppliedToAtLeast ar | otherwise = prag -lhsBindArity :: LHsBind GhcRn -> NameEnv Arity -> NameEnv Arity -lhsBindArity (L _ (FunBind { fun_id = id, fun_matches = ms })) env - = extendNameEnv env (unLoc id) (matchGroupArity ms) -lhsBindArity _ env = env -- PatBind/VarBind +lhsBindVisArity :: LHsBind GhcRn -> NameEnv Arity -> NameEnv Arity +lhsBindVisArity (L _ (FunBind { fun_id = id, fun_matches = ms })) env + = extendNameEnv env (unLoc id) (matchGroupVisArity ms) +lhsBindVisArity _ env = env -- PatBind/VarBind ----------------- ===================================== compiler/GHC/Types/Arity.hs ===================================== @@ -84,7 +84,14 @@ like Haskell, there is more than one way to count those arguments. forall a b. (Num a, Ord b) => a -> b -> a has arity <= 4 * `VisArity` is the syntactic notion of arity. It is the number of /visible/ - arguments, i.e. arguments that occur visibly in the source code. + arguments, i.e. arguments that occur visibly in the source code. For example: + f1 :: forall a. a -> a + f1 x = x + f2 :: forall a -> a -> a + f2 t x = x + Both have Arity 1 because there is one /value/ argument. + But f1 has VisArity 1 while f2 has VisArity 2, becuase f2 has a required + type argument. In a function call `f x y z`, we can confidently say that f's vis-arity >= 3, simply because we see three arguments [x,y,z]. We write (>=) rather than (==) ===================================== compiler/GHC/Types/InlinePragma.hs ===================================== @@ -104,7 +104,7 @@ import GHC.Prelude import GHC.Data.FastString import GHC.Hs.Extension -import GHC.Types.Arity (Arity) +import GHC.Types.Arity (VisArity) import GHC.Types.SourceText (SourceText(..)) import GHC.Utils.Binary import GHC.Utils.Outputable @@ -125,12 +125,13 @@ infixl 1 `setInlinePragmaActivation`, -- | The arity /at which to/ inline a function. -- This may differ from the function's syntactic arity. data InlineSaturation - = AppliedToAtLeast !Arity + = AppliedToAtLeast !VisArity -- ^ Inline only when applied to @n@ explicit - -- (non-type, non-dictionary) arguments. + -- (required type or value) arguments. -- -- That is, 'AppliedToAtLeast' describes the number of -- *source-code* arguments the thing must be applied to. + | AnySaturation -- ^ There does not exist an explicit number of arguments -- that the inlining process should be applied to. ===================================== compiler/GHC/Types/Var.hs ===================================== @@ -82,7 +82,7 @@ module GHC.Types.Var ( -- * PiTyBinder PiTyBinder(..), PiTyVarBinder, isInvisiblePiTyBinder, isInvisibleAnonPiTyBinder, - isVisiblePiTyBinder, + isVisiblePiTyBinder, isRuntimePiTyBinder, isTyBinder, isNamedPiTyBinder, isAnonPiTyBinder, namedPiTyBinder_maybe, anonPiTyBinderType_maybe, piTyBinderType, @@ -757,7 +757,12 @@ instance NamedThing tv => NamedThing (VarBndr tv flag) where -- not. See Note [PiTyBinders] data PiTyBinder = Named ForAllTyBinder -- A type-lambda binder, with a ForAllTyFlag - | Anon (Scaled Type) FunTyFlag -- A term-lambda binder. Type here can be CoercionTy. + -- Erased (not passed at runtime) if the binder is + -- a type variable; not erased if coercion variable + + | Anon (Scaled Type) FunTyFlag -- A term-lambda binder, passing a runtime value + -- The argument can be a constraint (incl dictionary) + -- or an ordinary value -- The arrow is described by the FunTyFlag deriving Data @@ -792,6 +797,12 @@ namedPiTyBinder_maybe :: PiTyBinder -> Maybe TyCoVar namedPiTyBinder_maybe (Named tv) = Just $ binderVar tv namedPiTyBinder_maybe _ = Nothing +isRuntimePiTyBinder :: PiTyBinder -> Bool +isRuntimePiTyBinder (Anon {}) = True -- Always passed at runtime +isRuntimePiTyBinder (Named (Bndr tcv _)) = isCoVar tcv + -- isCoVar: see Note [Why ForAllTy can quantify over a coercion variable] + -- and Note [Unused coercion variable in ForAllTy], in GHC.Core.TyCo.Rep + -- | Does this binder bind a variable that is /not/ erased? Returns -- 'True' for anonymous binders. isAnonPiTyBinder :: PiTyBinder -> Bool @@ -817,7 +828,7 @@ piTyBinderType (Named (Bndr tv _)) = varType tv piTyBinderType (Anon ty _) = scaledThing ty {- Note [PiTyBinders] -~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ But a type like forall a. Maybe a -> forall b. (a,b) -> b @@ -830,14 +841,18 @@ argument to a Pi-type. GHC Core currently supports two different Pi-types: * Anon ty1 fun_flag: a non-dependent function type, - written with ->, e.g. ty1 -> ty2 - represented as FunTy ty1 ty2. These are - lifted to Coercions with the corresponding FunCo. + written with ->, e.g. ty1 -> ty2 + represented as FunTy ty1 ty2. + + See wrinkle (PIT1) + + These are lifted to Coercions with the corresponding FunCo. + + * Named (Var tcv forall_flag): a dependent polytype, + written with forall, e.g. forall (a:*). ty + represented as ForAllTy (Bndr a v) ty - * Named (Var tv forall_flag) - A dependent compile-time-only polytype, - written with forall, e.g. forall (a:*). ty - represented as ForAllTy (Bndr a v) ty + See wrinkle (PIT2) Both forms of Pi-types classify terms/types that take an argument. In other words, if `x` is either a function or a polytype, `x arg` makes sense @@ -845,12 +860,16 @@ words, if `x` is either a function or a polytype, `x arg` makes sense Wrinkles -* The Anon constructor of PiTyBinder contains a FunTyFlag. Since +(PIT1) The Anon constructor of PiTyBinder contains a FunTyFlag. Since the PiTyBinder really only describes the /argument/ it should perhaps only have a TypeOrConstraint rather than a full FunTyFlag. But it's very convenient to have the full FunTyFlag, say in mkPiTys, so that's what we do. +(PIT2) The `tcv` in `Named (Var tcv forall_flag) is usually a type variable + but can exceptionally be a coercion variable: see + Note [Why ForAllTy can quantify over a coercion variable]. + If it's a type variable it will be erased; if coercion variable it will not. Note [VarBndrs, ForAllTyBinders, TyConBinders, and visibility] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ===================================== libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr ===================================== @@ -43,17 +43,17 @@ fusionElemFilter jump go1 eta fusionNotElemConcatMap - = \ x x1 -> + = \ x eta -> joinrec { go1 ds = case ds of { [] -> True; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> jump go1 ys; 1# -> False }; @@ -62,20 +62,20 @@ fusionNotElemConcatMap } } }; } in - jump go1 x1 + jump go1 eta fusionElemConcatMap - = \ x x1 -> + = \ x eta -> joinrec { go1 ds = case ds of { [] -> False; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> jump go1 ys; 1# -> True }; @@ -84,7 +84,7 @@ fusionElemConcatMap } } }; } in - jump go1 x1 + jump go1 eta fusionNotElemMap = \ x eta -> ===================================== libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr ===================================== @@ -77,25 +77,25 @@ fusionElemFilter jump go1 eta fusionNotElemConcatMap - = \ x x1 -> - case x1 of { + = \ x eta -> + case eta of { [] -> True; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> joinrec { go1 ds = case ds of { [] -> True; : y1 ys1 -> - case y1 of { I# x4 -> - case ==# x3 (+# x4 1#) of { + case y1 of { I# x3 -> + case ==# x2 (+# x3 1#) of { __DEFAULT -> - case ==# x3 (+# x4 2#) of { + case ==# x2 (+# x3 2#) of { __DEFAULT -> jump go1 ys1; 1# -> False }; @@ -113,25 +113,25 @@ fusionNotElemConcatMap } fusionElemConcatMap - = \ x x1 -> - case x1 of { + = \ x eta -> + case eta of { [] -> False; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> joinrec { go1 ds = case ds of { [] -> False; : y1 ys1 -> - case y1 of { I# x4 -> - case ==# x3 (+# x4 1#) of { + case y1 of { I# x3 -> + case ==# x2 (+# x3 1#) of { __DEFAULT -> - case ==# x3 (+# x4 2#) of { + case ==# x2 (+# x3 2#) of { __DEFAULT -> jump go1 ys1; 1# -> True }; ===================================== testsuite/tests/simplCore/should_compile/T27589.hs ===================================== @@ -0,0 +1,9 @@ +module T28589 where + +wombat :: Num a => a -> a +{-# INLINE wombat #-} +wombat x = x+x*x + +g :: Num a => [a] -> [a] +g ys = map wombat ys + -- wombat should not inline here ===================================== testsuite/tests/simplCore/should_compile/T27589.stderr ===================================== @@ -0,0 +1,3 @@ +wombat [InlPrag=INLINE (sat-args=1)] :: forall a. Num a => a -> a +wombat + map @a @a (wombat @a $dNum) ys ===================================== testsuite/tests/simplCore/should_compile/T27590.hs ===================================== @@ -0,0 +1,10 @@ +{-# LANGUAGE RequiredTypeArguments #-} + +module Foo where + +wombat :: forall a -> a -> Maybe a +{-# INLINE wombat #-} +wombat t x = Just x + +g y = wombat Int (y+y) + -- wombat /should/ inline here ===================================== testsuite/tests/simplCore/should_compile/T27590.stderr ===================================== @@ -0,0 +1,2 @@ +wombat [InlPrag=INLINE (sat-args=2)] :: forall a -> a -> Maybe a +wombat ===================================== testsuite/tests/simplCore/should_compile/all.T ===================================== @@ -609,3 +609,5 @@ test('T4081', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-a test('T27261', [extra_files(['T27261_aux.hs'])], multimod_compile, ['T27261', '-v0 -O']) test('T27296', [], makefile_test, ['T27296']) test('T27296b', [], makefile_test, ['T27296b']) +test('T27589', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques']) +test('T27590', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques']) ===================================== testsuite/tests/typecheck/should_compile/T27557.hs ===================================== @@ -0,0 +1,9 @@ +{-# LANGUAGE RequiredTypeArguments #-} + +module RequiredTypeArgumentsMkSymCo where + +import Data.Kind (Type) + +f :: forall a . forall (b :: Type) -> a -> a +f t = id +{-# INLINE f #-} ===================================== testsuite/tests/typecheck/should_compile/all.T ===================================== @@ -968,4 +968,4 @@ test('T24464', normal, compile, ['']) test('ExpansionQLIm', normal, compile, ['']) test('T23135', normal, compile, ['']) test('LazyFieldAnnotations', normal, compile, ['']) - +test('T27557', normal, compile, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d373dba276d5cd97c4cb3a218d5314d… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d373dba276d5cd97c4cb3a218d5314d… 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
0 0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 5 commits: hie files: Dump the type table when dumping with -ddump-hie
by Marge Bot (@marge-bot) 06 Aug '26

06 Aug '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: a10cb52a by Zubin Duggal at 2026-08-06T07:29:26-04:00 hie files: Dump the type table when dumping with -ddump-hie - - - - - a745b443 by Zubin Duggal at 2026-08-06T07:29:26-04:00 hie files: Take evidence for quantified constraints into account when saving evidence terms to the hie ast Fixes #25709 - - - - - 5f17ab12 by Simon Jakobi at 2026-08-06T07:29:28-04:00 testsuite: fix stale paths for the ghc-config build artifacts ghc-config.hs moved from testsuite/mk/ to testsuite/ghc-config/ in 6c7a49139c, but the .gitignore entry and the clean rule still referred to the old location. As a result the compiled ghc-config binary, which boilerplate.mk rebuilds on every make-driven test run, showed up as an untracked file and was never cleaned. Assisted-by: Claude Opus 5 - - - - - fecb9282 by Simon Peyton Jones at 2026-08-06T07:29:28-04:00 Documentation only ...driven by my investigation of #27591 - - - - - 1cab497c by Alan Zimmerman at 2026-08-06T07:29:29-04:00 EPA: Replace AnnPragma with individual types We introduced AnnPragma as a common type for all pragma usages wrapped in LocatedP / SrcSpanAnnP. Now that those are gone, and the AnnPragma moved into the TTG points for the given items, we can ensure that each carries only the annotations it needs. So we remove AnnPragma, and in its place bring in AnnCType AnnWarningTxt AnnOverlap AnnAnnDecl AnnPragSCC - - - - - 20 changed files: - compiler/GHC/Core/Class.hs - compiler/GHC/Driver/Main/Passes.hs - compiler/GHC/Hs/Decls.hs - compiler/GHC/Hs/Decls/Overlap.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/Iface/Ext/Types.hs - compiler/GHC/Parser.y - compiler/GHC/Parser/Annotation.hs - compiler/GHC/Rename/HsType.hs - compiler/GHC/Types/ForeignCall.hs - compiler/GHC/Types/Id/Make.hs - compiler/GHC/Unit/Module/Warnings.hs - testsuite/.gitignore - testsuite/Makefile - testsuite/tests/hiefile/should_compile/T24493.stderr - + testsuite/tests/hiefile/should_run/T25709.hs - + testsuite/tests/hiefile/should_run/T25709.stdout - testsuite/tests/hiefile/should_run/all.T - utils/check-exact/ExactPrint.hs - utils/haddock/haddock-api/src/Haddock/Types.hs Changes: ===================================== compiler/GHC/Core/Class.hs ===================================== @@ -84,9 +84,9 @@ data Class -- Here fun-deps are [([a,b],[c]), ([a,c],[b])] type FunDep a = ([a],[a]) -type ClassOpItem = (Id, DefMethInfo) - -- Selector function; contains unfolding - -- Default-method info +type ClassOpItem = ( Id -- Dictionary selector function + -- See Note [Dictionary selectors] + , DefMethInfo) -- Default-method info type DefMethInfo = Maybe (Name, DefMethSpec Type) -- Nothing No default method @@ -164,7 +164,19 @@ classMinimalDef :: Class -> ClassMinimalDef classMinimalDef Class{ classBody = ConcreteClass{ cls_min_def = d } } = d classMinimalDef _ = mkTrue -- TODO: make sure this is the right direction -{- +{- Note [Dictionary selectors] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Each `ClassOpItem` stores a dictionary selector `Id`: + +* The type of the selector is always closed, and has form + forall a1..an. C a1 .. an => blah + where `a1..an` are the class variables, and + `blah` is the method type. + See GHC.Types.Id.Make.mkDictSelId, which constructs them. + +* The selector has no unfolding, but one RULE. + See Note [ClassOp/DFun selection] in GHC.Tc.TyCl.Instance + Note [Associated type defaults] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is an example of associated type defaults: ===================================== compiler/GHC/Driver/Main/Passes.hs ===================================== @@ -92,7 +92,7 @@ import GHC.Iface.Make import GHC.Iface.Recomp import GHC.Iface.Tidy import GHC.Iface.Ext.Ast ( mkHieFile ) -import GHC.Iface.Ext.Types ( getAsts, hie_asts, hie_module ) +import GHC.Iface.Ext.Types ( getAsts, hie_asts, hie_module, hie_types ) import GHC.Iface.Ext.Binary ( readHieFile, writeHieFile , hie_file_result) import GHC.Iface.Ext.Debug ( diffFile, validateScopes ) @@ -167,7 +167,7 @@ import GHC.Data.StringBuffer import GHC.Data.Maybe import qualified GHC.Data.Strict as Strict - +import qualified Data.Array as A import Data.List ( nub, isPrefixOf, partition ) import qualified Data.List.NonEmpty as NE import Control.Monad @@ -332,7 +332,10 @@ extract_renamed_stuff mod_summary tc_result = do hieFile <- mkHieFile mod_summary tc_result (fromJust rn_info) let out_file = ml_hie_file $ ms_location mod_summary liftIO $ writeHieFile out_file hieFile - liftIO $ putDumpFileMaybe logger Opt_D_dump_hie "HIE AST" FormatHaskell (ppr $ hie_asts hieFile) + let hie_doc = + ppr (hie_asts hieFile) + $+$ ppr (A.assocs $ hie_types hieFile) + liftIO $ putDumpFileMaybe logger Opt_D_dump_hie "HIE AST" FormatHaskell hie_doc -- Validate HIE files when (gopt Opt_ValidateHie dflags) $ do ===================================== compiler/GHC/Hs/Decls.hs ===================================== @@ -1528,7 +1528,7 @@ instance OutputableBndrId p ************************************************************************ -} -type instance XHsAnnotation (GhcPass _) = (AnnPragma, SourceText) +type instance XHsAnnotation (GhcPass _) = (AnnAnnDecl, SourceText) type instance XXAnnDecl (GhcPass _) = DataConCantHappen instance (OutputableBndrId p) => Outputable (AnnDecl (GhcPass p)) where ===================================== compiler/GHC/Hs/Decls/Overlap.hs ===================================== @@ -26,7 +26,7 @@ import GHC.Prelude import GHC.Hs.Extension -import GHC.Parser.Annotation ( AnnPragma ) +import GHC.Parser.Annotation ( AnnOverlap ) import Language.Haskell.Syntax.Decls.Overlap import Language.Haskell.Syntax.Extension @@ -67,8 +67,8 @@ instance NFData OverlapFlag where instance Outputable OverlapFlag where ppr flag = ppr (overlapMode flag) <+> pprSafeOverlap (isSafeOverlap flag) -type instance XOverlapMode GhcPs = (SourceText, AnnPragma) -type instance XOverlapMode GhcRn = (SourceText, AnnPragma) +type instance XOverlapMode GhcPs = (SourceText, AnnOverlap) +type instance XOverlapMode GhcRn = (SourceText, AnnOverlap) type instance XOverlapMode GhcTc = SourceText type instance XXOverlapMode (GhcPass _) = DataConCantHappen ===================================== compiler/GHC/Hs/Expr.hs ===================================== @@ -612,7 +612,7 @@ instance NoAnn AnnFunRhs where -- --------------------------------------------------------------------- -type instance XSCC (GhcPass _) = (AnnPragma, SourceText) +type instance XSCC (GhcPass _) = (AnnPragSCC, SourceText) type instance XXPragE (GhcPass _) = DataConCantHappen type instance XCDotFieldOcc (GhcPass _) = AnnFieldLabel ===================================== compiler/GHC/Iface/Ext/Types.hs ===================================== @@ -159,6 +159,18 @@ data HieType a | HCoercionTy deriving (Functor, Foldable, Traversable, Eq) +instance Outputable a => Outputable (HieType a) where + ppr (HTyVarTy name) = ppr name + ppr (HAppTy fun arg) = parens $ ppr fun <+> ppr arg + ppr (HTyConApp tc args) = parens $ ppr tc <+> ppr args + ppr (HForAllTy ((name, ty), flag) body) = + text "forall" <+> ppr flag <+> ppr name O.<> text ":" <+> ppr ty O.<> text "." <+> ppr body + ppr (HFunTy mult arg res) = parens $ ppr arg <+> arrow <+> ppr res <+> ppr mult + ppr (HQualTy ctxt ty) = parens $ ppr ctxt <+> text "=>" <+> ppr ty + ppr (HLitTy lit) = ppr lit + ppr (HCastTy ty) = text "cast" <+> ppr ty + ppr HCoercionTy = text "<coercion>" + type HieTypeFlat = HieType TypeIndex -- | Roughly isomorphic to the original core 'Type'. @@ -222,6 +234,10 @@ instance Binary (HieArgs TypeIndex) where put_ bh (HieArgs xs) = put_ bh xs get bh = HieArgs <$> get bh +instance Outputable a => Outputable (HieArgs a) where + ppr (HieArgs args) = braces $ hsep $ punctuate comma $ map pprArg args + where pprArg (vis, ty) = (if vis then id else parens) (ppr ty) + -- A HiePath is just a lexical FastString. We use a lexical FastString to avoid -- non-determinism when printing or storing HieASTs which are sorted by their ===================================== compiler/GHC/Parser.y ===================================== @@ -1473,13 +1473,13 @@ inst_decl :: { LInstDecl GhcPs } overlap_pragma :: { Maybe (LocatedA (OverlapMode GhcPs)) } : '{-# OVERLAPPABLE' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Overlappable (getOVERLAPPABLE_PRAGs $1, - AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) } + AnnOverlap (glR $1) (epTok $2)))) } | '{-# OVERLAPPING' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Overlapping (getOVERLAPPING_PRAGs $1, - AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) } + AnnOverlap (glR $1) (epTok $2)))) } | '{-# OVERLAPS' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Overlaps (getOVERLAPS_PRAGs $1, - AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) } + AnnOverlap (glR $1) (epTok $2)))) } | '{-# INCOHERENT' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Incoherent (getINCOHERENT_PRAGs $1, - AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) } + AnnOverlap (glR $1) (epTok $2)))) } | {- empty -} { Nothing } deriv_strategy_no_via :: { LDerivStrategy GhcPs } @@ -1710,13 +1710,13 @@ datafam_inst_hdr :: { Located (Maybe (LHsContext GhcPs), HsOuterFamEqnTyVarBndrs capi_ctype :: { Maybe (LocatedA (CType GhcPs)) } capi_ctype : '{-# CTYPE' STRING STRING '#-}' {% fmap Just $ amsA' (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $3) - (AnnPragma (glR $1) (epTok $4) noAnn (glR $2) (glR $3) noAnn noAnn) + (AnnCType (glR $1) (epTok $4) (glR $2) (glR $3)) (Just (Header (getSTRINGs $2) (getSTRING $2))) (getSTRING $3)))} | '{-# CTYPE' STRING '#-}' {% fmap Just $ amsA' (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $2) - (AnnPragma (glR $1) (epTok $3) noAnn noAnn (glR $2) noAnn noAnn) + (AnnCType (glR $1) (epTok $3) noAnn (glR $2)) Nothing (getSTRING $2)))} | { Nothing } @@ -2078,11 +2078,11 @@ to varid (used for rule_vars), 'checkRuleTyVarBndrNames' must be updated. maybe_warning_pragma :: { Maybe (LWarningTxt GhcPs) } : '{-# DEPRECATED' strings '#-}' {% fmap Just $ amsA' (sLL $1 $> $ - DeprecatedTxt (getDEPRECATED_PRAGs $1, AnnPragma (glR $1) (epTok $3) (fst $ unLoc $2) noAnn noAnn noAnn noAnn) + DeprecatedTxt (getDEPRECATED_PRAGs $1, AnnWarningTxt (glR $1) (epTok $3) (fst $ unLoc $2)) (snd $ unLoc $2))} | '{-# WARNING' warning_category strings '#-}' {% fmap Just $ amsA' (sLL $1 $> $ - WarningTxt (getWARNING_PRAGs $1, AnnPragma (glR $1) (epTok $4) (fst $ unLoc $3) noAnn noAnn noAnn noAnn) + WarningTxt (getWARNING_PRAGs $1, AnnWarningTxt (glR $1) (epTok $4) (fst $ unLoc $3)) $2 (snd $ unLoc $3))} | {- empty -} { Nothing } @@ -2165,19 +2165,19 @@ stringlist :: { Located (OrdList (LocatedA (WithHsDocIdentifiers (StringLiteral annotation :: { LHsDecl GhcPs } : '{-# ANN' name_var aexp '#-}' {% runPV (unECP $3) >>= \ $3 -> amsA' (sLL $1 $> (AnnD noExtField $ HsAnnotation - (AnnPragma (glR $1) (epTok $4) noAnn noAnn noAnn noAnn noAnn, + (AnnAnnDecl (glR $1) (epTok $4) noAnn noAnn, (getANN_PRAGs $1)) (ValueAnnProvenance $2) $3)) } | '{-# ANN' 'type' otycon aexp '#-}' {% runPV (unECP $4) >>= \ $4 -> amsA' (sLL $1 $> (AnnD noExtField $ HsAnnotation - (AnnPragma (glR $1) (epTok $5) noAnn noAnn noAnn (epTok $2) noAnn, + (AnnAnnDecl (glR $1) (epTok $5) (epTok $2) noAnn, (getANN_PRAGs $1)) (TypeAnnProvenance $3) $4)) } | '{-# ANN' 'module' aexp '#-}' {% runPV (unECP $3) >>= \ $3 -> amsA' (sLL $1 $> (AnnD noExtField $ HsAnnotation - (AnnPragma (glR $1) (epTok $4) noAnn noAnn noAnn noAnn (epTok $2), + (AnnAnnDecl (glR $1) (epTok $4) noAnn (epTok $2), (getANN_PRAGs $1)) ModuleAnnProvenance $3)) } @@ -3052,12 +3052,12 @@ prag_e :: { Located (HsPragE GhcPs) } : '{-# SCC' STRING '#-}' {% do { scc <- getSCC $2 ; return (sLL $1 $> (HsPragSCC - (AnnPragma (glR $1) (epTok $3) noAnn (glR $2) noAnn noAnn noAnn, + (AnnPragSCC (glR $1) (epTok $3) (glR $2), (getSCC_PRAGs $1)) (StringLiteral (getSTRINGs $2) scc)))} } | '{-# SCC' VARID '#-}' { sLL $1 $> (HsPragSCC - (AnnPragma (glR $1) (epTok $3) noAnn (glR $2) noAnn noAnn noAnn, + (AnnPragSCC (glR $1) (epTok $3) (glR $2), (getSCC_PRAGs $1)) (StringLiteral NoSourceText (fastStringToShortText $ getVARID $2))) } ===================================== compiler/GHC/Parser/Annotation.hs ===================================== @@ -36,7 +36,7 @@ module GHC.Parser.Annotation ( AnnList(..), AnnListBrackets(..), AnnParen(..), - AnnPragma(..), + AnnCType(..),AnnWarningTxt(..),AnnOverlap(..),AnnAnnDecl(..),AnnPragSCC(..), AnnBooleanFormula(..), NameAnn(..), NameAdornment(..), NoEpAnns(..), @@ -627,15 +627,40 @@ data NameAdornment -- | exact print annotation used for capturing the locations of -- annotations in pragmas. -data AnnPragma - = AnnPragma { - apr_open :: EpaLocation, - apr_close :: EpToken "#-}", - apr_squares :: (EpToken "[", EpToken "]"), - apr_loc1 :: EpaLocation, - apr_loc2 :: EpaLocation, - apr_type :: EpToken "type", - apr_module :: EpToken "module" +data AnnCType + = AnnCType { + ac_open :: EpaLocation, + ac_close :: EpToken "#-}", + ac_loc1 :: EpaLocation, + ac_loc2 :: EpaLocation + } deriving (Data,Eq) + +data AnnWarningTxt + = AnnWarningTxt { + awt_open :: EpaLocation, + awt_close :: EpToken "#-}", + awt_squares :: (EpToken "[", EpToken "]") + } deriving (Data,Eq) + +data AnnOverlap + = AnnOverlap { + ao_open :: EpaLocation, + ao_close :: EpToken "#-}" + } deriving (Data,Eq) + +data AnnAnnDecl + = AnnAnnDecl { + ad_open :: EpaLocation, + ad_close :: EpToken "#-}", + ad_type :: EpToken "type", + ad_module :: EpToken "module" + } deriving (Data,Eq) + +data AnnPragSCC + = AnnPragSCC { + aps_open :: EpaLocation, + aps_close :: EpToken "#-}", + aps_loc1 :: EpaLocation } deriving (Data,Eq) -- --------------------------------------------------------------------- @@ -1020,8 +1045,20 @@ instance NoAnn a => NoAnn (AnnList a) where instance NoAnn NameAnn where noAnn = NameAnnTrailing [] -instance NoAnn AnnPragma where - noAnn = AnnPragma noAnn noAnn noAnn noAnn noAnn noAnn noAnn +instance NoAnn AnnCType where + noAnn = AnnCType noAnn noAnn noAnn noAnn + +instance NoAnn AnnWarningTxt where + noAnn = AnnWarningTxt noAnn noAnn noAnn + +instance NoAnn AnnOverlap where + noAnn = AnnOverlap noAnn noAnn + +instance NoAnn AnnAnnDecl where + noAnn = AnnAnnDecl noAnn noAnn noAnn noAnn + +instance NoAnn AnnPragSCC where + noAnn = AnnPragSCC noAnn noAnn noAnn instance NoAnn AnnParen where noAnn = AnnParens noAnn noAnn @@ -1107,7 +1144,23 @@ instance Outputable AnnListBrackets where ppr (ListBanana o c) = text "ListBanana" <+> ppr o <+> ppr c ppr ListNone = text "ListNone" -instance Outputable AnnPragma where - ppr (AnnPragma o c s l ca t m) - = text "AnnPragma" <+> ppr o <+> ppr c <+> ppr s <+> ppr l - <+> ppr ca <+> ppr ca <+> ppr t <+> ppr m +instance Outputable AnnCType where + ppr (AnnCType o c l ca) + = text "AnnCType" <+> ppr o <+> ppr c <+> ppr l + <+> ppr ca <+> ppr ca + +instance Outputable AnnWarningTxt where + ppr (AnnWarningTxt o c s) + = text "AnnWarningTxt" <+> ppr o <+> ppr c <+> ppr s + +instance Outputable AnnOverlap where + ppr (AnnOverlap o c) + = text "AnnOverlap" <+> ppr o <+> ppr c + +instance Outputable AnnAnnDecl where + ppr (AnnAnnDecl o c t m) + = text "AnnAnnDecl" <+> ppr o <+> ppr c <+> ppr t <+> ppr m + +instance Outputable AnnPragSCC where + ppr (AnnPragSCC o c l) + = text "AnnPragSCC" <+> ppr o <+> ppr c <+> ppr l ===================================== compiler/GHC/Rename/HsType.hs ===================================== @@ -1188,10 +1188,20 @@ bindHsOuterTyVarBndrs :: OutputableBndrFlag flag 'Renamed -> RnM (a, FreeNames) bindHsOuterTyVarBndrs doc mb_cls implicit_vars outer_bndrs thing_inside = case outer_bndrs of + HsOuterImplicit{} -> + -- Add an implicit `forall a1..an` at the top, where `a1..an` + -- are not-otherwise-in-scope type variables. + -- Used when there is no forall, or a /visible/ (forall a -> blah) + -- See Note [forall-or-nothing rule] in Language.Haskell.Syntax.Type rnImplicitTvOccs mb_cls implicit_vars $ \implicit_vars' -> thing_inside $ HsOuterImplicit { hso_ximplicit = implicit_vars' } + HsOuterExplicit{hso_bndrs = exp_bndrs} -> + -- The type already has an explicit, user-written, invisible forall, + -- so do not add an implicit forall + -- See Note [forall-or-nothing rule] in Language.Haskell.Syntax.Type + -- -- Note: If we pass mb_cls instead of Nothing below, bindLHsTyVarBndrs -- will use class variables for any names the user meant to bring in -- scope here. This is an explicit forall, so we want fresh names, not ===================================== compiler/GHC/Types/ForeignCall.hs ===================================== @@ -109,7 +109,7 @@ import Data.Data (Data) import Data.Functor ((<&>)) import Control.DeepSeq (NFData(..)) -import GHC.Parser.Annotation (AnnPragma, noAnn) +import GHC.Parser.Annotation (AnnCType, noAnn) {- ************************************************************************ @@ -216,7 +216,7 @@ defaultCType :: String -> CType (GhcPass p) defaultCType = CType (CTypeGhc NoSourceText NoSourceText noAnn) Nothing . packHText -mkCType :: SourceText -> SourceText -> AnnPragma -> Maybe (Header (GhcPass p)) -> HText -> CType (GhcPass p) +mkCType :: SourceText -> SourceText -> AnnCType -> Maybe (Header (GhcPass p)) -> HText -> CType (GhcPass p) mkCType x y ann m = CType (CTypeGhc x y ann) m @@ -303,7 +303,7 @@ data StaticTargetGhc = StaticTargetGhc data CTypeGhc = CTypeGhc { cTypeSourceText :: SourceText , cTypeOtherText :: SourceText - , cTypeAnn :: AnnPragma + , cTypeAnn :: AnnCType } deriving (Data, Eq) ===================================== compiler/GHC/Types/Id/Make.hs ===================================== @@ -480,7 +480,7 @@ Therefore there is no loss of generality if we make all selectors unrestricted. mkDictSelId :: Name -- Name of one of the *value* selectors -- (dictionary superclass or method) -> Class -> Id --- Important: see Note [ClassOp/DFun selection] in GHC.Tc.TyCl.Instance +-- See Note [Dictionary selectors] mkDictSelId name clas = mkGlobalId (ClassOpId clas terminating) name sel_ty info where ===================================== compiler/GHC/Unit/Module/Warnings.hs ===================================== @@ -158,8 +158,8 @@ warningTxtSame w1 w2 instance Outputable (InWarningCategory (GhcPass pass)) where ppr (InWarningCategory _ wt) = text "in" <+> doubleQuotes (ppr wt) -type instance XDeprecatedTxt (GhcPass _) = (SourceText, AnnPragma) -type instance XWarningTxt (GhcPass _) = (SourceText, AnnPragma) +type instance XDeprecatedTxt (GhcPass _) = (SourceText, AnnWarningTxt) +type instance XWarningTxt (GhcPass _) = (SourceText, AnnWarningTxt) type instance XXWarningTxt (GhcPass _) = DataConCantHappen type instance XInWarningCategory (GhcPass _) = (EpToken "in", SourceText) type instance XXInWarningCategory (GhcPass _) = DataConCantHappen ===================================== testsuite/.gitignore ===================================== @@ -72,7 +72,7 @@ mk/ghcconfig*_test___spaces_ghc*.exe.mk # NOTE: to edit this section in Vim, add your ignore annotations some where # in the list, select the entire section and say ':sort u' to sort it. -/mk/ghc-config +/ghc-config/ghc-config /tests/ado/ado001 /tests/annotations/should_compile/th/build_make ===================================== testsuite/Makefile ===================================== @@ -46,5 +46,6 @@ clean distclean maintainer-clean: $(RM) -f mk/*.o $(RM) -f mk/*.hi $(RM) -f mk/ghcconfig*.mk - $(RM) -f mk/ghc-config mk/ghc-config.exe + $(RM) -f ghc-config/ghc-config ghc-config/ghc-config.exe + $(RM) -f ghc-config/ghc-config.o ghc-config/ghc-config.hi $(RM) -f driver/*.pyc ===================================== testsuite/tests/hiefile/should_compile/T24493.stderr ===================================== @@ -1,3 +1,4 @@ + ==================== HIE AST ==================== File: T24493.hs Node@T24493.hs:(1,8)-(3,8): Source: From source @@ -25,9 +26,10 @@ Node@T24493.hs:(1,8)-(3,8): Source: From source Node@T24493.hs:3:6-8: Source: From source {(annotations: {(HsLit, HsExpr)}), (types: [0]), (identifier info: {})} - + +[(0, (GHC.Internal.Base.String {}))] Got valid scopes -Got no roundtrip errors \ No newline at end of file +Got no roundtrip errors ===================================== testsuite/tests/hiefile/should_run/T25709.hs ===================================== @@ -0,0 +1,40 @@ +{-# LANGUAGE QuantifiedConstraints#-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE AllowAmbiguousTypes #-} +module Main where + +import TestUtils +import qualified Data.Map.Strict as M +import qualified Data.Set as S +import Data.Either +import Data.Maybe +import Data.Bifunctor (first) +import GHC.Plugins (moduleNameString, nameStableString, nameOccName, occNameString, isDerivedOccName) +import GHC.Iface.Ext.Types + + +import Data.Typeable + +data Some c where + Some :: c a => a -> Some c + +extractSome :: (Typeable a, forall x. c x => Typeable x) => Some c -> Maybe a +extractSome (Some a) = cast a + +f :: (forall x. Ord x => Eq [x]) => () +f = () +{-# NOINLINE f #-} + +g :: () +g = f + +useQC :: forall c a. (c a, forall x. c x => Show x) => a -> String +useQC x = show x + +points :: [(Int,Int)] +points = [(22,26),(29, 5), (32, 13)] + +main = do + (df, hf) <- readTestHie "T25709.hie" + let refmap = generateReferencesMap $ getAsts $ hie_asts hf + traverse (explainEv df hf refmap) points ===================================== testsuite/tests/hiefile/should_run/T25709.stdout ===================================== @@ -0,0 +1,110 @@ +========================== +At point (22,26), we found: +========================== +┌ +│ $dTypeable at T25709.hs:22:14-19, of type: Typeable a +│ is an evidence variable bound by a let, depending on: [$dTypeable] +│ with scope: LocalScope T25709.hs:22:14-29 +│ +│ Defined at <no location info> +└ +| +`- ┌ + │ $dTypeable at T25709.hs:22:1-29, of type: Typeable a + │ is an evidence variable bound by a HsWrapper + │ with scope: LocalScope T25709.hs:22:1-29 + │ bound at: T25709.hs:22:1-29 + │ Defined at <no location info> + └ + +┌ +│ $dTypeable at T25709.hs:22:14-19, of type: Typeable a +│ is an evidence variable bound by a let, depending on: [df, irred] +│ with scope: LocalScope T25709.hs:22:14-29 +│ +│ Defined at <no location info> +└ +| ++- ┌ +| │ df at T25709.hs:22:1-29, of type: forall x. c x => Typeable x +| │ is an evidence variable bound by a HsWrapper +| │ with scope: LocalScope T25709.hs:22:1-29 +| │ bound at: T25709.hs:22:1-29 +| │ Defined at <no location info> +| └ +| +`- ┌ + │ irred at T25709.hs:22:14-19, of type: c a + │ is an evidence variable bound by a let, depending on: [irred] + │ with scope: LocalScope T25709.hs:22:14-29 + │ + │ Defined at <no location info> + └ + | + `- ┌ + │ irred at T25709.hs:22:14-19, of type: c a + │ is an evidence variable bound by a pattern + │ with scope: LocalScope T25709.hs:22:14-29 + │ + │ Defined at <no location info> + └ + +========================== +At point (29,5), we found: +========================== +┌ +│ df at T25709.hs:1:1, of type: forall x. Ord x => Eq [x] +│ is an evidence variable bound by a let, depending on: [$p1Ord, +│ $fEqList] +│ with scope: ModuleScope +│ +│ Defined at <no location info> +└ +| ++- ┌ +| │ $p1Ord at T25709.hs:1:1, of type: forall a. Ord a => Eq a +| │ is a usage of an external evidence variable +| │ Defined in `GHC.Internal.Classes' +| └ +| +`- ┌ + │ $fEqList at T25709.hs:1:1, of type: forall a. Eq a => Eq [a] + │ is a usage of an external evidence variable + │ Defined in `GHC.Internal.Classes' + └ + +========================== +At point (32,13), we found: +========================== +┌ +│ $dShow at T25709.hs:32:1-16, of type: Show a +│ is an evidence variable bound by a let, depending on: [df, irred] +│ with scope: LocalScope T25709.hs:32:1-16 +│ bound at: T25709.hs:32:1-16 +│ Defined at <no location info> +└ +| ++- ┌ +| │ df at T25709.hs:32:1-16, of type: forall x. c x => Show x +| │ is an evidence variable bound by a HsWrapper +| │ with scope: LocalScope T25709.hs:32:1-16 +| │ bound at: T25709.hs:32:1-16 +| │ Defined at <no location info> +| └ +| +`- ┌ + │ irred at T25709.hs:32:1-16, of type: c a + │ is an evidence variable bound by a let, depending on: [irred] + │ with scope: LocalScope T25709.hs:32:1-16 + │ bound at: T25709.hs:32:1-16 + │ Defined at <no location info> + └ + | + `- ┌ + │ irred at T25709.hs:32:1-16, of type: c a + │ is an evidence variable bound by a HsWrapper + │ with scope: LocalScope T25709.hs:32:1-16 + │ bound at: T25709.hs:32:1-16 + │ Defined at <no location info> + └ + ===================================== testsuite/tests/hiefile/should_run/all.T ===================================== @@ -8,4 +8,5 @@ test('HieVdq', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUti test('T23540', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('T23120', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('T24544', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) -test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) \ No newline at end of file +test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) +test('T25709', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) ===================================== utils/check-exact/ExactPrint.hs ===================================== @@ -288,10 +288,6 @@ instance HasTrailing [TrailingAnn] where trailing a = a setTrailing _ ts = ts -instance HasTrailing AnnPragma where - trailing _ = [] - setTrailing a _ = a - instance HasTrailing AnnParen where trailing _ = [] setTrailing a _ = a @@ -1559,22 +1555,22 @@ instance ExactPrint (WarningTxt GhcPs) where getAnnotationEntry _ = NoEntryVal setAnnotationAnchor a _ _ _ = a - exact (WarningTxt (src, AnnPragma o c (os,cs) l1 l2 t m) mb_cat ws) = do + exact (WarningTxt (src, AnnWarningTxt o c (os,cs)) mb_cat ws) = do o' <- markAnnOpen'' o src "{-# WARNING" mb_cat' <- markAnnotated mb_cat os' <- markEpToken os ws' <- mapM markAnnotated ws cs' <- markEpToken cs c' <- markEpToken c - return (WarningTxt (src, AnnPragma o' c' (os',cs') l1 l2 t m) mb_cat' ws') + return (WarningTxt (src, AnnWarningTxt o' c' (os',cs')) mb_cat' ws') - exact (DeprecatedTxt (src, AnnPragma o c (os,cs) l1 l2 t m) ws) = do + exact (DeprecatedTxt (src, AnnWarningTxt o c (os,cs)) ws) = do o' <- markAnnOpen'' o src "{-# DEPRECATED" os' <- markEpToken os ws' <- mapM markAnnotated ws cs' <- markEpToken cs c' <- markEpToken c - return (DeprecatedTxt (src, AnnPragma o' c' (os',cs') l1 l2 t m) ws') + return (DeprecatedTxt (src, AnnWarningTxt o' c' (os',cs')) ws') instance ExactPrint (InWarningCategory GhcPs) where getAnnotationEntry _ = NoEntryVal @@ -2251,35 +2247,35 @@ instance ExactPrint (OverlapMode GhcPs) where setAnnotationAnchor a _ _ _ = a -- NOTE: NoOverlap is only used in the typechecker - exact (NoOverlap (src, AnnPragma o c s l1 l2 t m)) = do + exact (NoOverlap (src, AnnOverlap o c)) = do o' <- markAnnOpen'' o src "{-# NO_OVERLAP" c' <- markEpToken c - return (NoOverlap (src, AnnPragma o' c' s l1 l2 t m)) + return (NoOverlap (src, AnnOverlap o' c')) - exact (Overlappable (src, AnnPragma o c s l1 l2 t m)) = do + exact (Overlappable (src, AnnOverlap o c)) = do o' <- markAnnOpen'' o src "{-# OVERLAPPABLE" c' <- markEpToken c - return (Overlappable (src, AnnPragma o' c' s l1 l2 t m)) + return (Overlappable (src, AnnOverlap o' c')) - exact (Overlapping (src, AnnPragma o c s l1 l2 t m)) = do + exact (Overlapping (src, AnnOverlap o c)) = do o' <- markAnnOpen'' o src "{-# OVERLAPPING" c' <- markEpToken c - return (Overlapping (src, AnnPragma o' c' s l1 l2 t m)) + return (Overlapping (src, AnnOverlap o' c')) - exact (Overlaps (src, AnnPragma o c s l1 l2 t m)) = do + exact (Overlaps (src, AnnOverlap o c)) = do o' <- markAnnOpen'' o src "{-# OVERLAPS" c' <- markEpToken c - return (Overlaps (src, AnnPragma o' c' s l1 l2 t m)) + return (Overlaps (src, AnnOverlap o' c')) - exact (Incoherent (src, AnnPragma o c s l1 l2 t m)) = do + exact (Incoherent (src, AnnOverlap o c)) = do o' <- markAnnOpen'' o src "{-# INCOHERENT" c' <- markEpToken c - return (Incoherent (src, AnnPragma o' c' s l1 l2 t m)) + return (Incoherent (src, AnnOverlap o' c')) - exact (NonCanonical (src, AnnPragma o c s l1 l2 t m)) = do + exact (NonCanonical (src, AnnOverlap o c)) = do o' <- markAnnOpen'' o src "{-# INCOHERENT" c' <- markEpToken c - return (Incoherent (src, AnnPragma o' c' s l1 l2 t m)) + return (Incoherent (src, AnnOverlap o' c')) -- --------------------------------------------------------------------- @@ -2706,7 +2702,7 @@ instance ExactPrint (AnnDecl GhcPs) where getAnnotationEntry _ = NoEntryVal setAnnotationAnchor a _ _ _ = a - exact (HsAnnotation (AnnPragma o c s l1 l2 t m, src) prov e) = do + exact (HsAnnotation (AnnAnnDecl o c t m, src) prov e) = do o' <- markAnnOpen'' o src "{-# ANN" (t', m', prov') <- case prov of @@ -2723,7 +2719,7 @@ instance ExactPrint (AnnDecl GhcPs) where e' <- markAnnotated e c' <- markEpToken c - return (HsAnnotation (AnnPragma o' c' s l1 l2 t' m',src) prov' e') + return (HsAnnotation (AnnAnnDecl o' c' t' m',src) prov' e') -- --------------------------------------------------------------------- @@ -3146,11 +3142,11 @@ instance ExactPrint (HsPragE GhcPs) where getAnnotationEntry HsPragSCC{} = NoEntryVal setAnnotationAnchor a _ _ _ = a - exact (HsPragSCC (AnnPragma o c s l1 l2 t m,st) sl) = do + exact (HsPragSCC (AnnPragSCC o c l1,st) sl) = do o' <- markAnnOpen'' o st "{-# SCC" l1' <- printStringAtAA l1 (sourceTextToString (stringLitSourceText sl) (unpackHText $ sl_fs sl)) c' <- markEpToken c - return (HsPragSCC (AnnPragma o' c' s l1' l2 t m,st) sl) + return (HsPragSCC (AnnPragSCC o' c' l1',st) sl) instance ExactPrint (HsTypedSplice GhcPs) where getAnnotationEntry _ = NoEntryVal @@ -4408,7 +4404,7 @@ instance Typeable p => ExactPrint (CType (GhcPass p)) where exact (CType ext mh ct) = do let stp = cTypeSourceText ext stct = cTypeOtherText ext - AnnPragma o c s l1 l2 t m = cTypeAnn ext + AnnCType o c l1 l2 = cTypeAnn ext o' <- markAnnOpen'' o stp "{-# CTYPE" l1' <- case mh of Nothing -> return l1 @@ -4416,7 +4412,7 @@ instance Typeable p => ExactPrint (CType (GhcPass p)) where printStringAtAA l1 (toSourceTextWithSuffix srcH "" "") l2' <- printStringAtAA l2 (toSourceTextWithSuffix stct (unpackHText ct) "") c' <- markEpToken c - return (CType (ext { cTypeAnn = AnnPragma o' c' s l1' l2' t m }) mh ct) + return (CType (ext { cTypeAnn = AnnCType o' c' l1' l2' }) mh ct) -- --------------------------------------------------------------------- ===================================== utils/haddock/haddock-api/src/Haddock/Types.hs ===================================== @@ -838,7 +838,7 @@ type instance Anno (HsSigType DocNameI) = SrcSpanAnnA type instance Anno (BooleanFormula DocNameI) = SrcSpanAnnBF type instance Anno (OverlapMode DocNameI) = SrcSpanAnnA type instance Anno (CType DocNameI) = SrcSpanAnnA -type instance Anno (Header DocNameI) = EpAnn AnnPragma +type instance Anno (Header DocNameI) = SrcSpanAnnA type instance Anno (HsModifierOf (LocatedA (HsType DocNameI)) DocNameI) = SrcSpanAnnA type instance Anno (HsContextDetails DocNameI a) = SrcSpanAnnA View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/528b0d8a5e58b3a5ef84f5e184f89e… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/528b0d8a5e58b3a5ef84f5e184f89e… 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
0 0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 4 commits: hie files: Dump the type table when dumping with -ddump-hie
by Marge Bot (@marge-bot) 06 Aug '26

06 Aug '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 185df3e6 by Zubin Duggal at 2026-08-06T04:58:20-04:00 hie files: Dump the type table when dumping with -ddump-hie - - - - - 268b2fe3 by Zubin Duggal at 2026-08-06T04:58:20-04:00 hie files: Take evidence for quantified constraints into account when saving evidence terms to the hie ast Fixes #25709 - - - - - 8db1de70 by Simon Jakobi at 2026-08-06T04:58:21-04:00 testsuite: fix stale paths for the ghc-config build artifacts ghc-config.hs moved from testsuite/mk/ to testsuite/ghc-config/ in 6c7a49139c, but the .gitignore entry and the clean rule still referred to the old location. As a result the compiled ghc-config binary, which boilerplate.mk rebuilds on every make-driven test run, showed up as an untracked file and was never cleaned. Assisted-by: Claude Opus 5 - - - - - 528b0d8a by Simon Peyton Jones at 2026-08-06T04:58:22-04:00 Documentation only ...driven by my investigation of #27591 - - - - - 11 changed files: - compiler/GHC/Core/Class.hs - compiler/GHC/Driver/Main/Passes.hs - compiler/GHC/Iface/Ext/Types.hs - compiler/GHC/Rename/HsType.hs - compiler/GHC/Types/Id/Make.hs - testsuite/.gitignore - testsuite/Makefile - testsuite/tests/hiefile/should_compile/T24493.stderr - + testsuite/tests/hiefile/should_run/T25709.hs - + testsuite/tests/hiefile/should_run/T25709.stdout - testsuite/tests/hiefile/should_run/all.T Changes: ===================================== compiler/GHC/Core/Class.hs ===================================== @@ -84,9 +84,9 @@ data Class -- Here fun-deps are [([a,b],[c]), ([a,c],[b])] type FunDep a = ([a],[a]) -type ClassOpItem = (Id, DefMethInfo) - -- Selector function; contains unfolding - -- Default-method info +type ClassOpItem = ( Id -- Dictionary selector function + -- See Note [Dictionary selectors] + , DefMethInfo) -- Default-method info type DefMethInfo = Maybe (Name, DefMethSpec Type) -- Nothing No default method @@ -164,7 +164,19 @@ classMinimalDef :: Class -> ClassMinimalDef classMinimalDef Class{ classBody = ConcreteClass{ cls_min_def = d } } = d classMinimalDef _ = mkTrue -- TODO: make sure this is the right direction -{- +{- Note [Dictionary selectors] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Each `ClassOpItem` stores a dictionary selector `Id`: + +* The type of the selector is always closed, and has form + forall a1..an. C a1 .. an => blah + where `a1..an` are the class variables, and + `blah` is the method type. + See GHC.Types.Id.Make.mkDictSelId, which constructs them. + +* The selector has no unfolding, but one RULE. + See Note [ClassOp/DFun selection] in GHC.Tc.TyCl.Instance + Note [Associated type defaults] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is an example of associated type defaults: ===================================== compiler/GHC/Driver/Main/Passes.hs ===================================== @@ -92,7 +92,7 @@ import GHC.Iface.Make import GHC.Iface.Recomp import GHC.Iface.Tidy import GHC.Iface.Ext.Ast ( mkHieFile ) -import GHC.Iface.Ext.Types ( getAsts, hie_asts, hie_module ) +import GHC.Iface.Ext.Types ( getAsts, hie_asts, hie_module, hie_types ) import GHC.Iface.Ext.Binary ( readHieFile, writeHieFile , hie_file_result) import GHC.Iface.Ext.Debug ( diffFile, validateScopes ) @@ -167,7 +167,7 @@ import GHC.Data.StringBuffer import GHC.Data.Maybe import qualified GHC.Data.Strict as Strict - +import qualified Data.Array as A import Data.List ( nub, isPrefixOf, partition ) import qualified Data.List.NonEmpty as NE import Control.Monad @@ -332,7 +332,10 @@ extract_renamed_stuff mod_summary tc_result = do hieFile <- mkHieFile mod_summary tc_result (fromJust rn_info) let out_file = ml_hie_file $ ms_location mod_summary liftIO $ writeHieFile out_file hieFile - liftIO $ putDumpFileMaybe logger Opt_D_dump_hie "HIE AST" FormatHaskell (ppr $ hie_asts hieFile) + let hie_doc = + ppr (hie_asts hieFile) + $+$ ppr (A.assocs $ hie_types hieFile) + liftIO $ putDumpFileMaybe logger Opt_D_dump_hie "HIE AST" FormatHaskell hie_doc -- Validate HIE files when (gopt Opt_ValidateHie dflags) $ do ===================================== compiler/GHC/Iface/Ext/Types.hs ===================================== @@ -159,6 +159,18 @@ data HieType a | HCoercionTy deriving (Functor, Foldable, Traversable, Eq) +instance Outputable a => Outputable (HieType a) where + ppr (HTyVarTy name) = ppr name + ppr (HAppTy fun arg) = parens $ ppr fun <+> ppr arg + ppr (HTyConApp tc args) = parens $ ppr tc <+> ppr args + ppr (HForAllTy ((name, ty), flag) body) = + text "forall" <+> ppr flag <+> ppr name O.<> text ":" <+> ppr ty O.<> text "." <+> ppr body + ppr (HFunTy mult arg res) = parens $ ppr arg <+> arrow <+> ppr res <+> ppr mult + ppr (HQualTy ctxt ty) = parens $ ppr ctxt <+> text "=>" <+> ppr ty + ppr (HLitTy lit) = ppr lit + ppr (HCastTy ty) = text "cast" <+> ppr ty + ppr HCoercionTy = text "<coercion>" + type HieTypeFlat = HieType TypeIndex -- | Roughly isomorphic to the original core 'Type'. @@ -222,6 +234,10 @@ instance Binary (HieArgs TypeIndex) where put_ bh (HieArgs xs) = put_ bh xs get bh = HieArgs <$> get bh +instance Outputable a => Outputable (HieArgs a) where + ppr (HieArgs args) = braces $ hsep $ punctuate comma $ map pprArg args + where pprArg (vis, ty) = (if vis then id else parens) (ppr ty) + -- A HiePath is just a lexical FastString. We use a lexical FastString to avoid -- non-determinism when printing or storing HieASTs which are sorted by their ===================================== compiler/GHC/Rename/HsType.hs ===================================== @@ -1188,10 +1188,20 @@ bindHsOuterTyVarBndrs :: OutputableBndrFlag flag 'Renamed -> RnM (a, FreeNames) bindHsOuterTyVarBndrs doc mb_cls implicit_vars outer_bndrs thing_inside = case outer_bndrs of + HsOuterImplicit{} -> + -- Add an implicit `forall a1..an` at the top, where `a1..an` + -- are not-otherwise-in-scope type variables. + -- Used when there is no forall, or a /visible/ (forall a -> blah) + -- See Note [forall-or-nothing rule] in Language.Haskell.Syntax.Type rnImplicitTvOccs mb_cls implicit_vars $ \implicit_vars' -> thing_inside $ HsOuterImplicit { hso_ximplicit = implicit_vars' } + HsOuterExplicit{hso_bndrs = exp_bndrs} -> + -- The type already has an explicit, user-written, invisible forall, + -- so do not add an implicit forall + -- See Note [forall-or-nothing rule] in Language.Haskell.Syntax.Type + -- -- Note: If we pass mb_cls instead of Nothing below, bindLHsTyVarBndrs -- will use class variables for any names the user meant to bring in -- scope here. This is an explicit forall, so we want fresh names, not ===================================== compiler/GHC/Types/Id/Make.hs ===================================== @@ -480,7 +480,7 @@ Therefore there is no loss of generality if we make all selectors unrestricted. mkDictSelId :: Name -- Name of one of the *value* selectors -- (dictionary superclass or method) -> Class -> Id --- Important: see Note [ClassOp/DFun selection] in GHC.Tc.TyCl.Instance +-- See Note [Dictionary selectors] mkDictSelId name clas = mkGlobalId (ClassOpId clas terminating) name sel_ty info where ===================================== testsuite/.gitignore ===================================== @@ -72,7 +72,7 @@ mk/ghcconfig*_test___spaces_ghc*.exe.mk # NOTE: to edit this section in Vim, add your ignore annotations some where # in the list, select the entire section and say ':sort u' to sort it. -/mk/ghc-config +/ghc-config/ghc-config /tests/ado/ado001 /tests/annotations/should_compile/th/build_make ===================================== testsuite/Makefile ===================================== @@ -46,5 +46,6 @@ clean distclean maintainer-clean: $(RM) -f mk/*.o $(RM) -f mk/*.hi $(RM) -f mk/ghcconfig*.mk - $(RM) -f mk/ghc-config mk/ghc-config.exe + $(RM) -f ghc-config/ghc-config ghc-config/ghc-config.exe + $(RM) -f ghc-config/ghc-config.o ghc-config/ghc-config.hi $(RM) -f driver/*.pyc ===================================== testsuite/tests/hiefile/should_compile/T24493.stderr ===================================== @@ -1,3 +1,4 @@ + ==================== HIE AST ==================== File: T24493.hs Node@T24493.hs:(1,8)-(3,8): Source: From source @@ -25,9 +26,10 @@ Node@T24493.hs:(1,8)-(3,8): Source: From source Node@T24493.hs:3:6-8: Source: From source {(annotations: {(HsLit, HsExpr)}), (types: [0]), (identifier info: {})} - + +[(0, (GHC.Internal.Base.String {}))] Got valid scopes -Got no roundtrip errors \ No newline at end of file +Got no roundtrip errors ===================================== testsuite/tests/hiefile/should_run/T25709.hs ===================================== @@ -0,0 +1,40 @@ +{-# LANGUAGE QuantifiedConstraints#-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE AllowAmbiguousTypes #-} +module Main where + +import TestUtils +import qualified Data.Map.Strict as M +import qualified Data.Set as S +import Data.Either +import Data.Maybe +import Data.Bifunctor (first) +import GHC.Plugins (moduleNameString, nameStableString, nameOccName, occNameString, isDerivedOccName) +import GHC.Iface.Ext.Types + + +import Data.Typeable + +data Some c where + Some :: c a => a -> Some c + +extractSome :: (Typeable a, forall x. c x => Typeable x) => Some c -> Maybe a +extractSome (Some a) = cast a + +f :: (forall x. Ord x => Eq [x]) => () +f = () +{-# NOINLINE f #-} + +g :: () +g = f + +useQC :: forall c a. (c a, forall x. c x => Show x) => a -> String +useQC x = show x + +points :: [(Int,Int)] +points = [(22,26),(29, 5), (32, 13)] + +main = do + (df, hf) <- readTestHie "T25709.hie" + let refmap = generateReferencesMap $ getAsts $ hie_asts hf + traverse (explainEv df hf refmap) points ===================================== testsuite/tests/hiefile/should_run/T25709.stdout ===================================== @@ -0,0 +1,110 @@ +========================== +At point (22,26), we found: +========================== +┌ +│ $dTypeable at T25709.hs:22:14-19, of type: Typeable a +│ is an evidence variable bound by a let, depending on: [$dTypeable] +│ with scope: LocalScope T25709.hs:22:14-29 +│ +│ Defined at <no location info> +└ +| +`- ┌ + │ $dTypeable at T25709.hs:22:1-29, of type: Typeable a + │ is an evidence variable bound by a HsWrapper + │ with scope: LocalScope T25709.hs:22:1-29 + │ bound at: T25709.hs:22:1-29 + │ Defined at <no location info> + └ + +┌ +│ $dTypeable at T25709.hs:22:14-19, of type: Typeable a +│ is an evidence variable bound by a let, depending on: [df, irred] +│ with scope: LocalScope T25709.hs:22:14-29 +│ +│ Defined at <no location info> +└ +| ++- ┌ +| │ df at T25709.hs:22:1-29, of type: forall x. c x => Typeable x +| │ is an evidence variable bound by a HsWrapper +| │ with scope: LocalScope T25709.hs:22:1-29 +| │ bound at: T25709.hs:22:1-29 +| │ Defined at <no location info> +| └ +| +`- ┌ + │ irred at T25709.hs:22:14-19, of type: c a + │ is an evidence variable bound by a let, depending on: [irred] + │ with scope: LocalScope T25709.hs:22:14-29 + │ + │ Defined at <no location info> + └ + | + `- ┌ + │ irred at T25709.hs:22:14-19, of type: c a + │ is an evidence variable bound by a pattern + │ with scope: LocalScope T25709.hs:22:14-29 + │ + │ Defined at <no location info> + └ + +========================== +At point (29,5), we found: +========================== +┌ +│ df at T25709.hs:1:1, of type: forall x. Ord x => Eq [x] +│ is an evidence variable bound by a let, depending on: [$p1Ord, +│ $fEqList] +│ with scope: ModuleScope +│ +│ Defined at <no location info> +└ +| ++- ┌ +| │ $p1Ord at T25709.hs:1:1, of type: forall a. Ord a => Eq a +| │ is a usage of an external evidence variable +| │ Defined in `GHC.Internal.Classes' +| └ +| +`- ┌ + │ $fEqList at T25709.hs:1:1, of type: forall a. Eq a => Eq [a] + │ is a usage of an external evidence variable + │ Defined in `GHC.Internal.Classes' + └ + +========================== +At point (32,13), we found: +========================== +┌ +│ $dShow at T25709.hs:32:1-16, of type: Show a +│ is an evidence variable bound by a let, depending on: [df, irred] +│ with scope: LocalScope T25709.hs:32:1-16 +│ bound at: T25709.hs:32:1-16 +│ Defined at <no location info> +└ +| ++- ┌ +| │ df at T25709.hs:32:1-16, of type: forall x. c x => Show x +| │ is an evidence variable bound by a HsWrapper +| │ with scope: LocalScope T25709.hs:32:1-16 +| │ bound at: T25709.hs:32:1-16 +| │ Defined at <no location info> +| └ +| +`- ┌ + │ irred at T25709.hs:32:1-16, of type: c a + │ is an evidence variable bound by a let, depending on: [irred] + │ with scope: LocalScope T25709.hs:32:1-16 + │ bound at: T25709.hs:32:1-16 + │ Defined at <no location info> + └ + | + `- ┌ + │ irred at T25709.hs:32:1-16, of type: c a + │ is an evidence variable bound by a HsWrapper + │ with scope: LocalScope T25709.hs:32:1-16 + │ bound at: T25709.hs:32:1-16 + │ Defined at <no location info> + └ + ===================================== testsuite/tests/hiefile/should_run/all.T ===================================== @@ -8,4 +8,5 @@ test('HieVdq', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUti test('T23540', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('T23120', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('T24544', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) -test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) \ No newline at end of file +test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) +test('T25709', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/363d13e0bcc526a8b7bfaccf52bf99… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/363d13e0bcc526a8b7bfaccf52bf99… 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
0 0
[Git][ghc/ghc][wip/sjakobi/udfm-placement] Use a pigeonhole sort for deterministic UniqDFM iteration
by Simon Jakobi (@sjakobi) 06 Aug '26

06 Aug '26
Simon Jakobi pushed to branch wip/sjakobi/udfm-placement at Glasgow Haskell Compiler / GHC Commits: 2b96b592 by Simon Jakobi at 2026-08-06T09:38:09+02:00 Use a pigeonhole sort for deterministic UniqDFM iteration Deterministic UniqDFM iteration used a list mergesort, allocating O(n log n) cons cells and contributing significantly to compiler allocations (#27459). Use a pigeonhole sort where appropriate, while retaining the mergesort fallback. See Note [Sorting a UDFM] and Note [Cost of deterministic iteration]. ------------------------- Metric Decrease: InstanceMatching InstanceMatching1 ManyAlternatives T12707 T13379 T13719 T24471 T27336 T5321FD T5321Fun T783 ------------------------- Assisted-by: gpt-5.6-sol via Codex CLI - - - - - 5 changed files: - compiler/GHC/Data/Word64Map/Internal.hs - compiler/GHC/Data/Word64Map/Lazy.hs - compiler/GHC/Data/Word64Map/Strict.hs - compiler/GHC/Data/Word64Map/Strict/Internal.hs - compiler/GHC/Types/Unique/DFM.hs Changes: ===================================== compiler/GHC/Data/Word64Map/Internal.hs ===================================== @@ -170,6 +170,7 @@ module GHC.Data.Word64Map.Internal ( , map , mapWithKey , traverseWithKey + , traverseWithKey_ , traverseMaybeWithKey , mapAccum , mapAccumWithKey @@ -2520,6 +2521,16 @@ traverseWithKey f = go | otherwise = liftA2 (Bin p m) (go l) (go r) {-# INLINE traverseWithKey #-} +-- | \(O(n)\). Visit each key\/value pair in ascending key order, discarding +-- the results. +traverseWithKey_ :: Applicative t => (Key -> a -> t ()) -> Word64Map a -> t () +traverseWithKey_ f = go + where + go Nil = pure () + go (Tip k v) = f k v + go (Bin _ _ l r) = go l *> go r +{-# INLINE traverseWithKey_ #-} + -- | \(O(n)\). The function @'mapAccum'@ threads an accumulating -- argument through the map in ascending order of keys. -- ===================================== compiler/GHC/Data/Word64Map/Lazy.hs ===================================== @@ -149,6 +149,7 @@ module GHC.Data.Word64Map.Lazy ( , WM.map , mapWithKey , traverseWithKey + , traverseWithKey_ , traverseMaybeWithKey , mapAccum , mapAccumWithKey ===================================== compiler/GHC/Data/Word64Map/Strict.hs ===================================== @@ -166,6 +166,7 @@ module GHC.Data.Word64Map.Strict ( , map , mapWithKey , traverseWithKey + , traverseWithKey_ , traverseMaybeWithKey , mapAccum , mapAccumWithKey ===================================== compiler/GHC/Data/Word64Map/Strict/Internal.hs ===================================== @@ -168,6 +168,7 @@ module GHC.Data.Word64Map.Strict.Internal ( , map , mapWithKey , traverseWithKey + , traverseWithKey_ , traverseMaybeWithKey , mapAccum , mapAccumWithKey @@ -330,6 +331,7 @@ import GHC.Data.Word64Map.Internal , toAscList , toDescList , toList + , traverseWithKey_ , union , unions , withoutKeys ===================================== compiler/GHC/Types/Unique/DFM.hs ===================================== @@ -14,6 +14,9 @@ See Note [Unique Determinism] in GHC.Types.Unique for explanation why @Unique@ o is not deterministic. -} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE UnboxedTuples #-} + {-# OPTIONS_GHC -Wall #-} module GHC.Types.Unique.DFM ( @@ -79,6 +82,9 @@ import Data.Functor.Classes (Eq1 (..)) import Data.List (sortBy) import Data.Function (on) import GHC.Types.Unique.FM (UniqFM, nonDetUFMToList, ufmToIntMap, unsafeIntMapToUFM) +import GHC.Data.SmallArray +import GHC.Exts (State#, build) +import GHC.ST (ST(..), runST) import Unsafe.Coerce import qualified GHC.Data.Word64Set as W @@ -96,10 +102,10 @@ import qualified GHC.Data.Word64Set as W -- This means `alterUDFM` consistent with `addToUDFM` and `adjustUDFM`, -- so that for example `alterUDFM id k = id` and `alterUDFM (fmap f) k = adjustUDFM f k` -- --- There is an implementation cost: each element is given a serial number --- as it is added, and `udfmToList` sorts its result by this serial --- number. So you should only use `UniqDFM` if you need the deterministic --- property. +-- There is an implementation cost: each element is given an insertion tag +-- as it is added, and functions like `udfmToList` or `eltsUDFM` order their +-- results by this tag (see Note [Cost of deterministic iteration]). So you +-- should only use `UniqDFM` if you need the deterministic property. -- -- `foldUDFM` also preserves determinism. -- @@ -112,7 +118,7 @@ import qualified GHC.Data.Word64Set as W -- -- -- There's more than one way to implement this. The implementation here tags --- every value with the insertion time that can later be used to sort the +-- every value with its insertion tag that can later be used to sort the -- values when asked to convert to a list. -- -- Updating an existing key keeps the old tag. This keeps the order stable for @@ -125,7 +131,7 @@ import qualified GHC.Data.Word64Set as W -- -- An alternative would be to have -- --- data UniqDFM ele = UDFM (M.IntMap ele) [ele] +-- data UniqDFM ele = UDFM (Word64Map ele) [ele] -- -- where the list determines the order. This makes deletion tricky as we'd -- only accumulate elements in that list, but makes merging easier as you @@ -133,11 +139,11 @@ import qualified GHC.Data.Word64Set as W -- Deletion can probably be done in amortized fashion when the size of the -- list is twice the size of the set. --- | A type of values tagged with insertion time +-- | A type of values carrying an insertion tag data TaggedVal val = TaggedVal !val - {-# UNPACK #-} !Int -- ^ insertion time + {-# UNPACK #-} !Int -- ^ insertion tag deriving stock (Data, Functor, Foldable, Traversable) taggedFst :: TaggedVal val -> val @@ -159,18 +165,30 @@ instance Eq val => Eq (TaggedVal val) where data UniqDFM key ele = UDFM !(M.Word64Map (TaggedVal ele)) -- A map where keys are Unique's values and - -- values are tagged with insertion time. - -- The invariant is that all the tags will - -- be distinct within a single map - {-# UNPACK #-} !Int -- Upper bound on the values' insertion - -- time. See Note [Overflow on plusUDFM] + -- values carry an insertion tag. + {-# UNPACK #-} !Int -- Upper bound on the values' insertion + -- tags. See Note [Overflow on plusUDFM] + -- See Note [UDFM invariants] deriving (Data, Functor) --- | Deterministic, in O(n log n). +{- Note [UDFM invariants] +~~~~~~~~~~~~~~~~~~~~~~~~~ +In a map (UDFM m ub): + + (a) The insertion tags of the elements of m are distinct. + (b) Every tag lies in [0, ub). + +Consequently ub >= size m. + +The tags determine the order of deterministic iteration (eltsUDFM, +udfmToList). See Note [Sorting a UDFM]. +-} + +-- | Deterministic. See Note [Cost of deterministic iteration]. instance Foldable (UniqDFM key) where foldr = foldUDFM --- | Deterministic, in O(n log n). +-- | Deterministic. See Note [Cost of deterministic iteration]. instance Traversable (UniqDFM key) where traverse f = fmap listToUDFM_Directly . traverse (\(u,a) -> (u,) <$> f a) @@ -264,8 +282,8 @@ plusUDFM_CK f udfml@(UDFM _ i) udfmr@(UDFM _ j) -- Note [Overflow on plusUDFM] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- There are multiple ways of implementing plusUDFM. --- The main problem that needs to be solved is overlap on times of --- insertion between different keys in two maps. +-- The main problem that needs to be solved is overlap on insertion +-- tags between different keys in two maps. -- Consider: -- -- A = fromList [(a, (x, 1))] @@ -325,13 +343,27 @@ elemUDFM :: Uniquable key => key -> UniqDFM key elt -> Bool elemUDFM k (UDFM m _i) = M.member (getKey $ getUnique k) m -- | Performs a deterministic fold over the UniqDFM. --- It's O(n log n) while the corresponding function on `UniqFM` is O(n). +-- +-- O(n) in the common case, with an O(n log n) fallback. +-- +-- See Note [Cost of deterministic iteration]. foldUDFM :: (elt -> a -> a) -> a -> UniqDFM key elt -> a {-# INLINE foldUDFM #-} --- This INLINE prevents a regression in !10568 -foldUDFM k z m = foldr k z (eltsUDFM m) - --- | Like 'foldUDFM' but the function also receives a key +-- Specialises k and z into M.foldr on the small-map path. +foldUDFM k z (UDFM m ub) + | M.compareSize m 1 /= GT = M.foldr (k . taggedFst) z m + | otherwise = fold_udfm k z m ub + +fold_udfm :: (elt -> a -> a) -> a -> M.Word64Map (TaggedVal elt) -> Int -> a +{-# NOINLINE fold_udfm #-} +-- Kept out of line so that foldUDFM's consumers don't inline the sort machinery. +fold_udfm k z m ub + | usePigeonholeSort m ub = foldr k z (pigeonholeSort ub (\_ tv -> tv) m) + | otherwise = foldr k z (map taggedFst (sort_it m)) + +-- | Like 'foldUDFM' but the function also receives a key. +-- +-- See Note [Cost of deterministic iteration]. foldWithKeyUDFM :: (Unique -> elt -> a -> a) -> a -> UniqDFM key elt -> a {-# INLINE foldWithKeyUDFM #-} -- This INLINE was copied from foldUDFM @@ -346,14 +378,113 @@ nonDetStrictFoldUDFM k z (UDFM m _i) = foldl' k' z m where k' acc (TaggedVal v _) = k v acc +{- Note [Cost of deterministic iteration] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Deterministic iteration -- foldUDFM, eltsUDFM, udfmToList, and everything +built on them -- orders elements by insertion tag. The element with the +smallest tag can sit anywhere in the map, so every tag must be inspected, +and, given a @UDFM m ub@ on the pigeonhole-sort path, an array with ub slots +must be filled, before the first element can be emitted (see +Note [Sorting a UDFM]). So beyond maps of a single element, deterministic +iteration cannot stream: demanding any of the result processes the whole +map. #27459 shows that cost hitting a consumer that only needed to know +whether the result was non-empty. + +So: to test for emptiness, use isNullUDFM rather than null on eltsUDFM; +for order-oblivious queries, prefer short-circuiting anyUDFM/allUDFM; and +if you don't need the deterministic order at all, use nonDetStrictFoldUDFM. +-} + +-- | Deterministic, in order of insertion. +-- +-- See Note [Sorting a UDFM] and Note [Cost of deterministic iteration]. eltsUDFM :: UniqDFM key elt -> [elt] -{-# INLINE eltsUDFM #-} --- The INLINE makes it a good producer (from the map) -eltsUDFM (UDFM m _i) = map taggedFst (sort_it m) +{-# INLINE eltsUDFM #-} -- so the small case is a good producer + -- This matters for T13719. +eltsUDFM (UDFM m ub) + | M.compareSize m 1 /= GT = build (\c n -> M.foldr (c . taggedFst) n m) + | otherwise = elts_udfm m ub + +elts_udfm :: M.Word64Map (TaggedVal elt) -> Int -> [elt] +{-# NOINLINE elts_udfm #-} +-- Kept out of line so that eltsUDFM's consumers don't inline the sort machinery. +elts_udfm m ub + | usePigeonholeSort m ub = pigeonholeSort ub (\_ tv -> tv) m + | otherwise = map taggedFst (sort_it m) sort_it :: M.Word64Map (TaggedVal elt) -> [TaggedVal elt] sort_it m = sortBy (compare `on` taggedSnd) (M.elems m) + +{- Note [Sorting a UDFM] +~~~~~~~~~~~~~~~~~~~~~~~~ +Deterministic iteration must yield a map's elements in order of their +insertion tags. The obvious way is to sort on the tags, but we can do better: +in (UDFM m ub) the tags are distinct indices into [0, ub) (see +Note [UDFM invariants]), so each element can simply be placed at its own +tag in an ub-slot array, which is then read back in index order. This is +pigeonhole sort, with one element per hole. + +Cost: writing the elements is O(n) for n = M.size m, while allocating the +array and reading it back are O(ub). Since n <= ub the total is O(ub). No +comparisons are made. + +So the method wins only while the array stays dense, and ub never shrinks +(overwrites keep bumping it, delete/filter shrink n but not ub). +usePigeonholeSort therefore takes this path only when ub <= 4 * n, which +bounds its cost at O(n), and falls back to the O(n log n) comparison sort +otherwise. + +Unfilled slots contain a TaggedVal with tag -1 and value +@unsafeCoerce () :: r@. This is safe because the value is never used: only +slots with non-negative tags are read. + +pigeonholeSort also avoids intermediate lists: it fills the array by +traversing the map directly, and emits its readout with 'build', so the foldr +in fold_udfm fuses with it. This contributes significantly to the allocation +reductions in InstanceMatching1 in !16292. +-} + +-- | @ub <= 4 * size m@, computed without a full 'M.size' traversal. +usePigeonholeSort :: M.Word64Map a -> Int -> Bool +usePigeonholeSort m ub = M.compareSize m ceil_ub_div_4 /= LT + where + ceil_ub_div_4 = (ub + 3) `div` 4 -- ceil(ub/4): ub <= 4*n iff n >= ceil(ub/4) + +-- | Order the map's elements by tag. The tags must be distinct and in +-- @[0, ub)@, and @mk@ must preserve them. See Note [Sorting a UDFM]. +pigeonholeSort :: forall e r. Int + -> (M.Key -> TaggedVal e -> TaggedVal r) + -> M.Word64Map (TaggedVal e) + -> [r] +{-# INLINE pigeonholeSort #-} -- Specialise mk and enable foldr/build fusion. +pigeonholeSort ub mk m = build gen + where + -- The tag -1 marks unfilled slots; the value field is never read, but it + -- is strict, so it needs a WHNF value of type r. See Note [Sorting a UDFM]. + hole :: TaggedVal r + hole = TaggedVal (unsafeCoerce ()) (-1) + + fill :: SmallMutableArray s (TaggedVal r) -> State# s -> (# State# s, () #) + fill marr s = case M.traverseWithKey_ write m of ST st -> st s + where + write k tv = ST (\s' -> + (# writeSmallArray marr (taggedSnd tv) (mk k tv) s', () #)) + + gen :: forall b. (r -> b -> b) -> b -> b + gen cons nil = runST (ST (\s0 -> + case newSmallArray ub hole s0 of + (# s1, marr #) -> case fill marr s1 of + (# s2, () #) -> case unsafeFreezeSmallArray marr s2 of + (# s3, arr #) -> (# s3, readout arr 0 #))) + where + readout :: SmallArray (TaggedVal r) -> Int -> b + readout arr j + | j >= ub = nil + | t < 0 = readout arr (j + 1) + | otherwise = cons v (readout arr (j + 1)) + where TaggedVal v t = indexSmallArray arr j + filterUDFM :: (elt -> Bool) -> UniqDFM key elt -> UniqDFM key elt filterUDFM p (UDFM m i) = UDFM (M.filter (\(TaggedVal v _) -> p v) m) i @@ -371,11 +502,22 @@ udfmRestrictKeysSet (UDFM val_set i) set = in UDFM (M.restrictKeys val_set key_set) i -- | Converts `UniqDFM` to a list, with elements in deterministic order. --- It's O(n log n) while the corresponding function on `UniqFM` is O(n). +-- +-- O(n) in the common case, with an O(n log n) fallback. +-- +-- See Note [Cost of deterministic iteration]. udfmToList :: UniqDFM key elt -> [(Unique, elt)] -udfmToList (UDFM m _i) = - [ (mkUniqueGrimily k, taggedFst v) - | (k, v) <- sortBy (compare `on` (taggedSnd . snd)) $ M.toList m ] +-- NB: no INLINE, unlike eltsUDFM. udfmToList's one hot consumer is +-- traverseUSDFM in the pattern-match checker, which doesn't fuse. Inlining +-- the size dispatch into it regresses T17836. +udfmToList (UDFM m ub) + | M.compareSize m 1 /= GT = + M.foldrWithKey (\k tv r -> (mkUniqueGrimily k, taggedFst tv) : r) [] m + | usePigeonholeSort m ub = pigeonholeSort ub + (\k tv -> TaggedVal (mkUniqueGrimily k, taggedFst tv) (taggedSnd tv)) m + | otherwise = + [ (mkUniqueGrimily k, taggedFst v) + | (k, v) <- sortBy (compare `on` (taggedSnd . snd)) $ M.toList m ] -- Determines whether two 'UniqDFM's contain the same keys. equalKeysUDFM :: UniqDFM key a -> UniqDFM key b -> Bool View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2b96b592906f14df41a8eb358c5d8d3… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2b96b592906f14df41a8eb358c5d8d3… 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
0 0
[Git][ghc/ghc][wip/T27557] Fix three bugs related to required type args and INLINE pragmas
by Simon Peyton Jones (@simonpj) 06 Aug '26

06 Aug '26
Simon Peyton Jones pushed to branch wip/T27557 at Glasgow Haskell Compiler / GHC Commits: 69780256 by Simon Peyton Jones at 2026-08-06T08:12:33+01:00 Fix three bugs related to required type args and INLINE pragmas * `GHC.Core.Opt.Arity.mkEtaForAllMCo` got the visibility flags back to front, leading to a Lint error (#27557) * The arity in an InlineSaturation is the VisArity not the Arity; the two can differ when we have "required" type arguments. This made the INLINE pragma argument counting go wrong in `makeCorePair` (#27590). * When a simple binding has a type signature, we take special path in `tcPolyCheck`, leading to an outer `AbsBinds` that has no dictionaries, even when the binding is in fact overloaded. That confused the inline-arity computation in `makeCorePair` (#27589). The latter two are fixed using the new function `GHC.HsToCore.Binds.findSatArity`. That actually simplifies the API of `makeCorePair`, which is nice. The first bug is fixed by swapping the visiblity flags in `GHC.Core.Opt.Arity.mkEtaForAllMCo` Getting the INLINE behaviour right led to some perf changes: * Runtime /halved/ on T7954 due to better specialisation * Compile time increased by 6% in T21839c because a bit more inlining happened, as it always should have done. * For some reason compile-time max-bytes-used dropped by 30% on T27336, but only on one build configuration Geometric mean effect on our compile time benchmarks is +0.1%. Metric Decrease: T27336 T7954 Metric Increase: T21839c - - - - - 21 changed files: - + changelog.d/T27557 - + changelog.d/T27589 - compiler/GHC/Core/Opt/Arity.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/HsToCore/Binds.hs - compiler/GHC/HsToCore/Match.hs - compiler/GHC/HsToCore/Ticks.hs - compiler/GHC/Tc/Gen/Bind.hs - compiler/GHC/Tc/Gen/Sig.hs - compiler/GHC/Types/Arity.hs - compiler/GHC/Types/InlinePragma.hs - compiler/GHC/Types/Var.hs - libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr - libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr - + testsuite/tests/simplCore/should_compile/T27589.hs - + testsuite/tests/simplCore/should_compile/T27589.stderr - + testsuite/tests/simplCore/should_compile/T27590.hs - + testsuite/tests/simplCore/should_compile/T27590.stderr - testsuite/tests/simplCore/should_compile/all.T - + testsuite/tests/typecheck/should_compile/T27557.hs - testsuite/tests/typecheck/should_compile/all.T Changes: ===================================== changelog.d/T27557 ===================================== @@ -0,0 +1,8 @@ +section: compiler +issues: #27577 +mrs: !16433 +synopsis: + Fix a Core Lint error involving RequiredTypeArguments +description: + Fixes an issue with a coercion being used for eta expansion storing + the wrong visibility information, which caused a Core Lint error. ===================================== changelog.d/T27589 ===================================== @@ -0,0 +1,10 @@ +section: compiler +issues: #27589 #27590 +mrs: !16433 +synopsis: + Fixes to arity computations +description: + The arity computation for INLINE pragmas now correctly takes into + account required type arguments. Separately, the arity computation + in ``tcPolyCheck`` now consistently handles dictionary arguments, fixing + a short-cut codepath which didn't ===================================== compiler/GHC/Core/Opt/Arity.hs ===================================== @@ -2370,11 +2370,15 @@ mkEtaForAllMCo (Bndr tcv vis) ty mco | otherwise -> mk_fco (mkRepReflCo ty) MCo co -> mk_fco co where - mk_fco co = MCo (mkForAllCo tcv vis coreTyLamForAllTyFlag MRefl co) + mk_fco co = MCo (mkForAllCo tcv coreTyLamForAllTyFlag vis MRefl co) -- coreTyLamForAllTyFlag: See Note [The EtaInfo mechanism], particularly -- the (EtaInfo Invariant). (sym co) wraps a lambda that always has -- a ForAllTyFlag of coreTyLamForAllTyFlag; see Note [Required foralls in Core] -- in GHC.Core.TyCo.Rep + -- + -- Orientation: remember, the output of mkEtaForAllCo goes into an `EI bs mco`, + -- and is SymCo'd in `etaInfoAbs`. Hence the orientation of the visibility + -- flags. A bit of a brain-strain (#27557). {- ************************************************************************ ===================================== compiler/GHC/Hs/Expr.hs ===================================== @@ -1687,10 +1687,11 @@ isSingletonMatchGroup matches | otherwise = False -matchGroupArity :: MatchGroup (GhcPass id) body -> Arity +matchGroupVisArity :: MatchGroup (GhcPass id) body -> VisArity -- This is called before type checking, when mg_arg_tys is not set -matchGroupArity MG { mg_alts = L _ [] } = 1 -- See Note [Empty mg_alts] -matchGroupArity MG { mg_alts = L _ (alt1 : _) } = count isVisArgLPat (hsLMatchPats alt1) +-- Returns the "visible arity" of the MatchGroup i.e. including required type arguments. +matchGroupVisArity MG { mg_alts = L _ [] } = 1 -- See Note [Empty mg_alts] +matchGroupVisArity MG { mg_alts = L _ (alt1 : _) } = count isVisArgLPat (hsLMatchPats alt1) hsLMatchPats :: LMatch (GhcPass id) body -> [LPat (GhcPass id)] hsLMatchPats (L _ (Match { m_pats = L _ pats })) = pats ===================================== compiler/GHC/HsToCore/Binds.hs ===================================== @@ -69,7 +69,7 @@ import GHC.Types.InlinePragma import GHC.Types.Name import GHC.Types.Var.Set import GHC.Types.Var.Env -import GHC.Types.Var( EvVar, mkLocalVar ) +import GHC.Types.Var( EvVar, mkLocalVar, isRuntimePiTyBinder ) import GHC.Types.SrcLoc import GHC.Types.Basic import GHC.Types.Unique.Set( nonDetEltsUniqSet ) @@ -196,7 +196,7 @@ dsHsBind dflags (VarBind { var_id = var = do { core_expr <- dsLExpr expr -- Dictionary bindings are always VarBinds, -- so we only need do this here - ; let core_bind@(id,_) = makeCorePair dflags var False 0 core_expr + ; let core_bind@(id,_) = makeCorePair dflags var False core_expr force_var = if xopt LangExt.Strict dflags then [id] else [] @@ -211,11 +211,11 @@ dsHsBind dflags b@(FunBind { fun_id = L loc fun ; let body' = mkOptTickBox tick body rhs = core_wrap (mkLams args body') - core_binds@(id,_) = makeCorePair dflags fun False 0 rhs + core_binds@(id,_) = makeCorePair dflags fun False rhs force_var -- Bindings are strict when -XStrict is enabled | xopt LangExt.Strict dflags - , matchGroupArity matches == 0 -- no need to force lambdas + , matchGroupVisArity matches == 0 -- no need to force lambdas = [id] | isBangedHsBind b = [id] @@ -303,7 +303,7 @@ dsAbsBinds dflags tyvars dicts exports ; let global_id' = addIdSpecialisations global_id rules main_bind = makeCorePair dflags global_id' (isDefaultMethod prags) - (dictArity dicts) rhs + rhs ; return (force_vars', fromOL spec_binds ++ [main_bind]) } } @@ -386,7 +386,7 @@ dsAbsBinds dflags tyvars dicts exports mk_aux_bind (lcl_id, rhs) = let lcl_w_inline = lookupVarEnv inline_env lcl_id `orElse` lcl_id in - makeCorePair dflags lcl_w_inline False 0 rhs + makeCorePair dflags lcl_w_inline False rhs inline_env :: IdEnv Id -- Maps a monomorphic local Id to one with -- the inline pragma from the source @@ -437,9 +437,9 @@ dsAbsBinds dflags tyvars dicts exports -- the unfolding in the interface file is made in `GHC.Iface.Tidy.addExternal` -- using this information. ------------------------ -makeCorePair :: DynFlags -> Id -> Bool -> Arity -> CoreExpr +makeCorePair :: DynFlags -> Id -> Bool -> CoreExpr -> (Id, CoreExpr) -makeCorePair dflags gbl_id is_default_method dict_arity rhs +makeCorePair dflags gbl_id is_default_method rhs | is_default_method -- Default methods are *always* inlined -- See Note [INLINE and default methods] in GHC.Tc.TyCl.Instance = (gbl_id `setIdUnfolding` mkCompulsoryUnfolding' simpl_opts rhs, rhs) @@ -456,22 +456,43 @@ makeCorePair dflags gbl_id is_default_method dict_arity rhs inline_prag = idInlinePragma gbl_id inlinable_unf = mkInlinableUnfolding simpl_opts StableUserSrc rhs inline_pair - | AppliedToAtLeast arity <- inlinePragmaSaturation inline_prag + | AppliedToAtLeast vis_arity <- inlinePragmaSaturation inline_prag -- Add an Unfolding for an INLINE (but not for NOINLINE) -- And eta-expand the RHS; see Note [Eta-expanding INLINE things] - , let real_arity = dict_arity + arity - -- NB: The arity passed to mkInlineUnfoldingWithArity - -- must take account of the dictionaries - = ( gbl_id `setIdUnfolding` mkInlineUnfoldingWithArity simpl_opts StableUserSrc real_arity rhs - , etaExpand real_arity rhs) + , let runtime_arity = findSatArity vis_arity (idType gbl_id) + -- NB: runtime_arity: the arity passed to mkInlineUnfoldingWithArity + -- must take account of dictionaries and required type args + = ( gbl_id `setIdUnfolding` mkInlineUnfoldingWithArity simpl_opts StableUserSrc + runtime_arity rhs + , etaExpand runtime_arity rhs) | otherwise = pprTrace "makeCorePair: arity missing" (ppr gbl_id) $ (gbl_id `setIdUnfolding` mkInlineUnfoldingNoArity simpl_opts StableUserSrc rhs, rhs) -dictArity :: [Var] -> Arity --- Don't count coercion variables in arity -dictArity dicts = count isId dicts +findSatArity :: VisArity -> Type -> Arity +-- Given the VisArity, find the value Arity of the function. +-- This is the number of runtime-value arguments the function must be applied +-- to before the INLINE pragma fires and inlines the function +-- We must: +-- add one for each invisible dictionary arg; and +-- subtract one for each required type argment +findSatArity vis_arity ty + = go vis_arity pi_bndrs + where + (pi_bndrs, _) = splitPiTys ty + + go vis_arity (bndr : bndrs) + | isInvisiblePiTyBinder bndr = add_bndr bndr (go vis_arity bndrs) + | vis_arity == 0 = 0 + | otherwise = add_bndr bndr (go (vis_arity-1) bndrs) + go vis_arity [] + | vis_arity == 0 = 0 + | otherwise = pprPanic "findSatArity" (ppr vis_arity $$ ppr ty) + + add_bndr :: PiTyBinder -> Arity -> Arity + add_bndr bndr ar | isRuntimePiTyBinder bndr = ar+1 + | otherwise = ar {- Note [Desugaring AbsBinds] ===================================== compiler/GHC/HsToCore/Match.hs ===================================== @@ -737,21 +737,21 @@ Call @match@ with all of this information! -- There are three possible cases for matchWrapper's scrutinees argument: -- -- 1. Nothing Used for FunBind, HsLam, HsLamcase, where there is no explicit scrutinee --- The MatchGroup may have matchGroupArity of 0 or more. Examples: --- f p1 q1 = ... -- matchGroupArity 2 +-- The MatchGroup may have matchGroupVisArity of 0 or more. Examples: +-- f p1 q1 = ... -- matchGroupVisArity 2 -- f p2 q2 = ... -- -- \cases | g1 -> ... -- matchGroupArity 0 -- | g2 -> ... -- -- 2. Just [e] Used for HsCase, RecordUpd; exactly one scrutinee --- The MatchGroup has matchGroupArity of exactly 1. Example: --- case e of p1 -> e1 -- matchGroupArity 1 +-- The MatchGroup has matchGroupVisArity of exactly 1. Example: +-- case e of p1 -> e1 -- matchGroupVisArity 1 -- p2 -> e2 -- -- 3. Just es Used for HsCmdLamCase; zero or more scrutinees -- The MatchGroup has matchGroupArity of (length es). Example: --- \cases p1 q1 -> returnA -< ... -- matchGroupArity 2 +-- \cases p1 q1 -> returnA -< ... -- matchGroupVisArity 2 -- p2 q2 -> ... matchWrapper ===================================== compiler/GHC/HsToCore/Ticks.hs ===================================== @@ -288,7 +288,7 @@ addTickLHsBind (L pos (funBind@(FunBind { fun_id = L _ id, fun_matches = matches -- We don't want to generate code for blacklisted positions -- We don't want redundant ticks on simple pattern bindings -- We don't want to tick non-exported bindings in TickExportedFunctions - let simple = matchGroupArity matches == 0 + let simple = matchGroupVisArity matches == 0 -- A binding is a "simple pattern binding" if it is a -- funbind with zero patterns toplev = null decl_path ===================================== compiler/GHC/Tc/Gen/Bind.hs ===================================== @@ -808,7 +808,7 @@ checkMonomorphismRestriction mbis lbinds restricted (VarBind { var_ext = x }) = dataConCantHappen x restricted b@(PatSynBind {}) = pprPanic "isRestrictedGroup/unrestricted" (ppr b) - restricted_match mg = matchGroupArity mg == 0 + restricted_match mg = matchGroupVisArity mg == 0 -- No args => like a pattern binding -- Some args => a function binding ===================================== compiler/GHC/Tc/Gen/Sig.hs ===================================== @@ -599,26 +599,26 @@ mkPragEnv sigs binds Nothing -> sig -- See Note [Pattern synonym inline arity] -- ar_env maps a local to the arity of its definition - ar_env :: NameEnv Arity - ar_env = foldr lhsBindArity emptyNameEnv binds + ar_env :: NameEnv VisArity + ar_env = foldr lhsBindVisArity emptyNameEnv binds -addInlinePragArity :: Arity -> LSig GhcRn -> LSig GhcRn +addInlinePragArity :: VisArity -> LSig GhcRn -> LSig GhcRn addInlinePragArity ar (L l (InlineSig x nm inl)) = L l (InlineSig x nm (add_inl_arity ar inl)) addInlinePragArity ar (L l (SpecSig x nm ty inl)) = L l (SpecSig x nm ty (add_inl_arity ar inl)) addInlinePragArity ar (L l (SpecSigE n x e inl)) = L l (SpecSigE n x e (add_inl_arity ar inl)) addInlinePragArity _ sig = sig -add_inl_arity :: Arity -> InlinePragma GhcRn -> InlinePragma GhcRn +add_inl_arity :: VisArity -> InlinePragma GhcRn -> InlinePragma GhcRn add_inl_arity ar prag@(InlinePragma { inl_inline = inl_spec }) | Inline {} <- inl_spec -- Add arity only for real INLINE pragmas, not INLINABLE = prag `setInlinePragmaSaturation` AppliedToAtLeast ar | otherwise = prag -lhsBindArity :: LHsBind GhcRn -> NameEnv Arity -> NameEnv Arity -lhsBindArity (L _ (FunBind { fun_id = id, fun_matches = ms })) env - = extendNameEnv env (unLoc id) (matchGroupArity ms) -lhsBindArity _ env = env -- PatBind/VarBind +lhsBindVisArity :: LHsBind GhcRn -> NameEnv Arity -> NameEnv Arity +lhsBindVisArity (L _ (FunBind { fun_id = id, fun_matches = ms })) env + = extendNameEnv env (unLoc id) (matchGroupVisArity ms) +lhsBindVisArity _ env = env -- PatBind/VarBind ----------------- ===================================== compiler/GHC/Types/Arity.hs ===================================== @@ -84,7 +84,14 @@ like Haskell, there is more than one way to count those arguments. forall a b. (Num a, Ord b) => a -> b -> a has arity <= 4 * `VisArity` is the syntactic notion of arity. It is the number of /visible/ - arguments, i.e. arguments that occur visibly in the source code. + arguments, i.e. arguments that occur visibly in the source code. For example: + f1 :: forall a. a -> a + f1 x = x + f2 :: forall a -> a -> a + f2 t x = x + Both have Arity 1 because there is one /value/ argument. + But f1 has VisArity 1 while f2 has VisArity 2, becuase f2 has a required + type argument. In a function call `f x y z`, we can confidently say that f's vis-arity >= 3, simply because we see three arguments [x,y,z]. We write (>=) rather than (==) ===================================== compiler/GHC/Types/InlinePragma.hs ===================================== @@ -104,7 +104,7 @@ import GHC.Prelude import GHC.Data.FastString import GHC.Hs.Extension -import GHC.Types.Arity (Arity) +import GHC.Types.Arity (VisArity) import GHC.Types.SourceText (SourceText(..)) import GHC.Utils.Binary import GHC.Utils.Outputable @@ -125,12 +125,13 @@ infixl 1 `setInlinePragmaActivation`, -- | The arity /at which to/ inline a function. -- This may differ from the function's syntactic arity. data InlineSaturation - = AppliedToAtLeast !Arity + = AppliedToAtLeast !VisArity -- ^ Inline only when applied to @n@ explicit - -- (non-type, non-dictionary) arguments. + -- (required type or value) arguments. -- -- That is, 'AppliedToAtLeast' describes the number of -- *source-code* arguments the thing must be applied to. + | AnySaturation -- ^ There does not exist an explicit number of arguments -- that the inlining process should be applied to. ===================================== compiler/GHC/Types/Var.hs ===================================== @@ -82,7 +82,7 @@ module GHC.Types.Var ( -- * PiTyBinder PiTyBinder(..), PiTyVarBinder, isInvisiblePiTyBinder, isInvisibleAnonPiTyBinder, - isVisiblePiTyBinder, + isVisiblePiTyBinder, isRuntimePiTyBinder, isTyBinder, isNamedPiTyBinder, isAnonPiTyBinder, namedPiTyBinder_maybe, anonPiTyBinderType_maybe, piTyBinderType, @@ -757,7 +757,12 @@ instance NamedThing tv => NamedThing (VarBndr tv flag) where -- not. See Note [PiTyBinders] data PiTyBinder = Named ForAllTyBinder -- A type-lambda binder, with a ForAllTyFlag - | Anon (Scaled Type) FunTyFlag -- A term-lambda binder. Type here can be CoercionTy. + -- Erased (not passed at runtime) if the binder is + -- a type variable; not erased if coercion variable + + | Anon (Scaled Type) FunTyFlag -- A term-lambda binder, passing a runtime value + -- The argument can be a constraint (incl dictionary) + -- or an ordinary value -- The arrow is described by the FunTyFlag deriving Data @@ -792,6 +797,12 @@ namedPiTyBinder_maybe :: PiTyBinder -> Maybe TyCoVar namedPiTyBinder_maybe (Named tv) = Just $ binderVar tv namedPiTyBinder_maybe _ = Nothing +isRuntimePiTyBinder :: PiTyBinder -> Bool +isRuntimePiTyBinder (Anon {}) = True -- Always passed at runtime +isRuntimePiTyBinder (Named (Bndr tcv _)) = isCoVar tcv + -- isCoVar: see Note [Why ForAllTy can quantify over a coercion variable] + -- and Note [Unused coercion variable in ForAllTy], in GHC.Core.TyCo.Rep + -- | Does this binder bind a variable that is /not/ erased? Returns -- 'True' for anonymous binders. isAnonPiTyBinder :: PiTyBinder -> Bool @@ -817,7 +828,7 @@ piTyBinderType (Named (Bndr tv _)) = varType tv piTyBinderType (Anon ty _) = scaledThing ty {- Note [PiTyBinders] -~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~ But a type like forall a. Maybe a -> forall b. (a,b) -> b @@ -830,14 +841,18 @@ argument to a Pi-type. GHC Core currently supports two different Pi-types: * Anon ty1 fun_flag: a non-dependent function type, - written with ->, e.g. ty1 -> ty2 - represented as FunTy ty1 ty2. These are - lifted to Coercions with the corresponding FunCo. + written with ->, e.g. ty1 -> ty2 + represented as FunTy ty1 ty2. + + See wrinkle (PIT1) + + These are lifted to Coercions with the corresponding FunCo. + + * Named (Var tcv forall_flag): a dependent polytype, + written with forall, e.g. forall (a:*). ty + represented as ForAllTy (Bndr a v) ty - * Named (Var tv forall_flag) - A dependent compile-time-only polytype, - written with forall, e.g. forall (a:*). ty - represented as ForAllTy (Bndr a v) ty + See wrinkle (PIT2) Both forms of Pi-types classify terms/types that take an argument. In other words, if `x` is either a function or a polytype, `x arg` makes sense @@ -845,12 +860,16 @@ words, if `x` is either a function or a polytype, `x arg` makes sense Wrinkles -* The Anon constructor of PiTyBinder contains a FunTyFlag. Since +(PIT1) The Anon constructor of PiTyBinder contains a FunTyFlag. Since the PiTyBinder really only describes the /argument/ it should perhaps only have a TypeOrConstraint rather than a full FunTyFlag. But it's very convenient to have the full FunTyFlag, say in mkPiTys, so that's what we do. +(PIT2) The `tcv` in `Named (Var tcv forall_flag) is usually a type variable + but can exceptionally be a coercion variable: see + Note [Why ForAllTy can quantify over a coercion variable]. + If it's a type variable it will be erased; if coercion variable it will not. Note [VarBndrs, ForAllTyBinders, TyConBinders, and visibility] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ===================================== libraries/base/tests/perf/ElemFusionUnknownList_O1.stderr ===================================== @@ -43,17 +43,17 @@ fusionElemFilter jump go1 eta fusionNotElemConcatMap - = \ x x1 -> + = \ x eta -> joinrec { go1 ds = case ds of { [] -> True; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> jump go1 ys; 1# -> False }; @@ -62,20 +62,20 @@ fusionNotElemConcatMap } } }; } in - jump go1 x1 + jump go1 eta fusionElemConcatMap - = \ x x1 -> + = \ x eta -> joinrec { go1 ds = case ds of { [] -> False; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> jump go1 ys; 1# -> True }; @@ -84,7 +84,7 @@ fusionElemConcatMap } } }; } in - jump go1 x1 + jump go1 eta fusionNotElemMap = \ x eta -> ===================================== libraries/base/tests/perf/ElemFusionUnknownList_O2.stderr ===================================== @@ -77,25 +77,25 @@ fusionElemFilter jump go1 eta fusionNotElemConcatMap - = \ x x1 -> - case x1 of { + = \ x eta -> + case eta of { [] -> True; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> joinrec { go1 ds = case ds of { [] -> True; : y1 ys1 -> - case y1 of { I# x4 -> - case ==# x3 (+# x4 1#) of { + case y1 of { I# x3 -> + case ==# x2 (+# x3 1#) of { __DEFAULT -> - case ==# x3 (+# x4 2#) of { + case ==# x2 (+# x3 2#) of { __DEFAULT -> jump go1 ys1; 1# -> False }; @@ -113,25 +113,25 @@ fusionNotElemConcatMap } fusionElemConcatMap - = \ x x1 -> - case x1 of { + = \ x eta -> + case eta of { [] -> False; : y ys -> - case y of { I# x2 -> - case x of { I# x3 -> - case ==# x3 (+# x2 1#) of { + case y of { I# x1 -> + case x of { I# x2 -> + case ==# x2 (+# x1 1#) of { __DEFAULT -> - case ==# x3 (+# x2 2#) of { + case ==# x2 (+# x1 2#) of { __DEFAULT -> joinrec { go1 ds = case ds of { [] -> False; : y1 ys1 -> - case y1 of { I# x4 -> - case ==# x3 (+# x4 1#) of { + case y1 of { I# x3 -> + case ==# x2 (+# x3 1#) of { __DEFAULT -> - case ==# x3 (+# x4 2#) of { + case ==# x2 (+# x3 2#) of { __DEFAULT -> jump go1 ys1; 1# -> True }; ===================================== testsuite/tests/simplCore/should_compile/T27589.hs ===================================== @@ -0,0 +1,9 @@ +module T28589 where + +wombat :: Num a => a -> a +{-# INLINE wombat #-} +wombat x = x+x*x + +g :: Num a => [a] -> [a] +g ys = map wombat ys + -- wombat should not inline here ===================================== testsuite/tests/simplCore/should_compile/T27589.stderr ===================================== @@ -0,0 +1,3 @@ +wombat [InlPrag=INLINE (sat-args=1)] :: forall a. Num a => a -> a +wombat + map @a @a (wombat @a $dNum) ys ===================================== testsuite/tests/simplCore/should_compile/T27590.hs ===================================== @@ -0,0 +1,10 @@ +{-# LANGUAGE RequiredTypeArguments #-} + +module Foo where + +wombat :: forall a -> a -> Maybe a +{-# INLINE wombat #-} +wombat t x = Just x + +g y = wombat Int (y+y) + -- wombat /should/ inline here ===================================== testsuite/tests/simplCore/should_compile/T27590.stderr ===================================== @@ -0,0 +1,2 @@ +wombat [InlPrag=INLINE (sat-args=2)] :: forall a -> a -> Maybe a +wombat ===================================== testsuite/tests/simplCore/should_compile/all.T ===================================== @@ -609,3 +609,5 @@ test('T4081', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-a test('T27261', [extra_files(['T27261_aux.hs'])], multimod_compile, ['T27261', '-v0 -O']) test('T27296', [], makefile_test, ['T27296']) test('T27296b', [], makefile_test, ['T27296b']) +test('T27589', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques']) +test('T27590', [grep_errmsg(r'wombat')], compile, ['-O -ddump-simpl -dno-typeable-binds -dsuppress-uniques']) ===================================== testsuite/tests/typecheck/should_compile/T27557.hs ===================================== @@ -0,0 +1,9 @@ +{-# LANGUAGE RequiredTypeArguments #-} + +module RequiredTypeArgumentsMkSymCo where + +import Data.Kind (Type) + +f :: forall a . forall (b :: Type) -> a -> a +f t = id +{-# INLINE f #-} ===================================== testsuite/tests/typecheck/should_compile/all.T ===================================== @@ -968,4 +968,4 @@ test('T24464', normal, compile, ['']) test('ExpansionQLIm', normal, compile, ['']) test('T23135', normal, compile, ['']) test('LazyFieldAnnotations', normal, compile, ['']) - +test('T27557', normal, compile, ['']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/69780256b9dd0e748f357cb980e83fc… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/69780256b9dd0e748f357cb980e83fc… 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
0 0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 3 commits: hie files: Dump the type table when dumping with -ddump-hie
by Marge Bot (@marge-bot) 06 Aug '26

06 Aug '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 74b6ede2 by Zubin Duggal at 2026-08-05T20:31:38-04:00 hie files: Dump the type table when dumping with -ddump-hie - - - - - 0df17cd1 by Zubin Duggal at 2026-08-05T20:31:38-04:00 hie files: Take evidence for quantified constraints into account when saving evidence terms to the hie ast Fixes #25709 - - - - - 363d13e0 by Simon Jakobi at 2026-08-05T20:31:39-04:00 testsuite: fix stale paths for the ghc-config build artifacts ghc-config.hs moved from testsuite/mk/ to testsuite/ghc-config/ in 6c7a49139c, but the .gitignore entry and the clean rule still referred to the old location. As a result the compiled ghc-config binary, which boilerplate.mk rebuilds on every make-driven test run, showed up as an untracked file and was never cleaned. Assisted-by: Claude Opus 5 - - - - - 8 changed files: - compiler/GHC/Driver/Main/Passes.hs - compiler/GHC/Iface/Ext/Types.hs - testsuite/.gitignore - testsuite/Makefile - testsuite/tests/hiefile/should_compile/T24493.stderr - + testsuite/tests/hiefile/should_run/T25709.hs - + testsuite/tests/hiefile/should_run/T25709.stdout - testsuite/tests/hiefile/should_run/all.T Changes: ===================================== compiler/GHC/Driver/Main/Passes.hs ===================================== @@ -92,7 +92,7 @@ import GHC.Iface.Make import GHC.Iface.Recomp import GHC.Iface.Tidy import GHC.Iface.Ext.Ast ( mkHieFile ) -import GHC.Iface.Ext.Types ( getAsts, hie_asts, hie_module ) +import GHC.Iface.Ext.Types ( getAsts, hie_asts, hie_module, hie_types ) import GHC.Iface.Ext.Binary ( readHieFile, writeHieFile , hie_file_result) import GHC.Iface.Ext.Debug ( diffFile, validateScopes ) @@ -167,7 +167,7 @@ import GHC.Data.StringBuffer import GHC.Data.Maybe import qualified GHC.Data.Strict as Strict - +import qualified Data.Array as A import Data.List ( nub, isPrefixOf, partition ) import qualified Data.List.NonEmpty as NE import Control.Monad @@ -332,7 +332,10 @@ extract_renamed_stuff mod_summary tc_result = do hieFile <- mkHieFile mod_summary tc_result (fromJust rn_info) let out_file = ml_hie_file $ ms_location mod_summary liftIO $ writeHieFile out_file hieFile - liftIO $ putDumpFileMaybe logger Opt_D_dump_hie "HIE AST" FormatHaskell (ppr $ hie_asts hieFile) + let hie_doc = + ppr (hie_asts hieFile) + $+$ ppr (A.assocs $ hie_types hieFile) + liftIO $ putDumpFileMaybe logger Opt_D_dump_hie "HIE AST" FormatHaskell hie_doc -- Validate HIE files when (gopt Opt_ValidateHie dflags) $ do ===================================== compiler/GHC/Iface/Ext/Types.hs ===================================== @@ -159,6 +159,18 @@ data HieType a | HCoercionTy deriving (Functor, Foldable, Traversable, Eq) +instance Outputable a => Outputable (HieType a) where + ppr (HTyVarTy name) = ppr name + ppr (HAppTy fun arg) = parens $ ppr fun <+> ppr arg + ppr (HTyConApp tc args) = parens $ ppr tc <+> ppr args + ppr (HForAllTy ((name, ty), flag) body) = + text "forall" <+> ppr flag <+> ppr name O.<> text ":" <+> ppr ty O.<> text "." <+> ppr body + ppr (HFunTy mult arg res) = parens $ ppr arg <+> arrow <+> ppr res <+> ppr mult + ppr (HQualTy ctxt ty) = parens $ ppr ctxt <+> text "=>" <+> ppr ty + ppr (HLitTy lit) = ppr lit + ppr (HCastTy ty) = text "cast" <+> ppr ty + ppr HCoercionTy = text "<coercion>" + type HieTypeFlat = HieType TypeIndex -- | Roughly isomorphic to the original core 'Type'. @@ -222,6 +234,10 @@ instance Binary (HieArgs TypeIndex) where put_ bh (HieArgs xs) = put_ bh xs get bh = HieArgs <$> get bh +instance Outputable a => Outputable (HieArgs a) where + ppr (HieArgs args) = braces $ hsep $ punctuate comma $ map pprArg args + where pprArg (vis, ty) = (if vis then id else parens) (ppr ty) + -- A HiePath is just a lexical FastString. We use a lexical FastString to avoid -- non-determinism when printing or storing HieASTs which are sorted by their ===================================== testsuite/.gitignore ===================================== @@ -72,7 +72,7 @@ mk/ghcconfig*_test___spaces_ghc*.exe.mk # NOTE: to edit this section in Vim, add your ignore annotations some where # in the list, select the entire section and say ':sort u' to sort it. -/mk/ghc-config +/ghc-config/ghc-config /tests/ado/ado001 /tests/annotations/should_compile/th/build_make ===================================== testsuite/Makefile ===================================== @@ -46,5 +46,6 @@ clean distclean maintainer-clean: $(RM) -f mk/*.o $(RM) -f mk/*.hi $(RM) -f mk/ghcconfig*.mk - $(RM) -f mk/ghc-config mk/ghc-config.exe + $(RM) -f ghc-config/ghc-config ghc-config/ghc-config.exe + $(RM) -f ghc-config/ghc-config.o ghc-config/ghc-config.hi $(RM) -f driver/*.pyc ===================================== testsuite/tests/hiefile/should_compile/T24493.stderr ===================================== @@ -1,3 +1,4 @@ + ==================== HIE AST ==================== File: T24493.hs Node@T24493.hs:(1,8)-(3,8): Source: From source @@ -25,9 +26,10 @@ Node@T24493.hs:(1,8)-(3,8): Source: From source Node@T24493.hs:3:6-8: Source: From source {(annotations: {(HsLit, HsExpr)}), (types: [0]), (identifier info: {})} - + +[(0, (GHC.Internal.Base.String {}))] Got valid scopes -Got no roundtrip errors \ No newline at end of file +Got no roundtrip errors ===================================== testsuite/tests/hiefile/should_run/T25709.hs ===================================== @@ -0,0 +1,40 @@ +{-# LANGUAGE QuantifiedConstraints#-} +{-# LANGUAGE UndecidableInstances #-} +{-# LANGUAGE AllowAmbiguousTypes #-} +module Main where + +import TestUtils +import qualified Data.Map.Strict as M +import qualified Data.Set as S +import Data.Either +import Data.Maybe +import Data.Bifunctor (first) +import GHC.Plugins (moduleNameString, nameStableString, nameOccName, occNameString, isDerivedOccName) +import GHC.Iface.Ext.Types + + +import Data.Typeable + +data Some c where + Some :: c a => a -> Some c + +extractSome :: (Typeable a, forall x. c x => Typeable x) => Some c -> Maybe a +extractSome (Some a) = cast a + +f :: (forall x. Ord x => Eq [x]) => () +f = () +{-# NOINLINE f #-} + +g :: () +g = f + +useQC :: forall c a. (c a, forall x. c x => Show x) => a -> String +useQC x = show x + +points :: [(Int,Int)] +points = [(22,26),(29, 5), (32, 13)] + +main = do + (df, hf) <- readTestHie "T25709.hie" + let refmap = generateReferencesMap $ getAsts $ hie_asts hf + traverse (explainEv df hf refmap) points ===================================== testsuite/tests/hiefile/should_run/T25709.stdout ===================================== @@ -0,0 +1,110 @@ +========================== +At point (22,26), we found: +========================== +┌ +│ $dTypeable at T25709.hs:22:14-19, of type: Typeable a +│ is an evidence variable bound by a let, depending on: [$dTypeable] +│ with scope: LocalScope T25709.hs:22:14-29 +│ +│ Defined at <no location info> +└ +| +`- ┌ + │ $dTypeable at T25709.hs:22:1-29, of type: Typeable a + │ is an evidence variable bound by a HsWrapper + │ with scope: LocalScope T25709.hs:22:1-29 + │ bound at: T25709.hs:22:1-29 + │ Defined at <no location info> + └ + +┌ +│ $dTypeable at T25709.hs:22:14-19, of type: Typeable a +│ is an evidence variable bound by a let, depending on: [df, irred] +│ with scope: LocalScope T25709.hs:22:14-29 +│ +│ Defined at <no location info> +└ +| ++- ┌ +| │ df at T25709.hs:22:1-29, of type: forall x. c x => Typeable x +| │ is an evidence variable bound by a HsWrapper +| │ with scope: LocalScope T25709.hs:22:1-29 +| │ bound at: T25709.hs:22:1-29 +| │ Defined at <no location info> +| └ +| +`- ┌ + │ irred at T25709.hs:22:14-19, of type: c a + │ is an evidence variable bound by a let, depending on: [irred] + │ with scope: LocalScope T25709.hs:22:14-29 + │ + │ Defined at <no location info> + └ + | + `- ┌ + │ irred at T25709.hs:22:14-19, of type: c a + │ is an evidence variable bound by a pattern + │ with scope: LocalScope T25709.hs:22:14-29 + │ + │ Defined at <no location info> + └ + +========================== +At point (29,5), we found: +========================== +┌ +│ df at T25709.hs:1:1, of type: forall x. Ord x => Eq [x] +│ is an evidence variable bound by a let, depending on: [$p1Ord, +│ $fEqList] +│ with scope: ModuleScope +│ +│ Defined at <no location info> +└ +| ++- ┌ +| │ $p1Ord at T25709.hs:1:1, of type: forall a. Ord a => Eq a +| │ is a usage of an external evidence variable +| │ Defined in `GHC.Internal.Classes' +| └ +| +`- ┌ + │ $fEqList at T25709.hs:1:1, of type: forall a. Eq a => Eq [a] + │ is a usage of an external evidence variable + │ Defined in `GHC.Internal.Classes' + └ + +========================== +At point (32,13), we found: +========================== +┌ +│ $dShow at T25709.hs:32:1-16, of type: Show a +│ is an evidence variable bound by a let, depending on: [df, irred] +│ with scope: LocalScope T25709.hs:32:1-16 +│ bound at: T25709.hs:32:1-16 +│ Defined at <no location info> +└ +| ++- ┌ +| │ df at T25709.hs:32:1-16, of type: forall x. c x => Show x +| │ is an evidence variable bound by a HsWrapper +| │ with scope: LocalScope T25709.hs:32:1-16 +| │ bound at: T25709.hs:32:1-16 +| │ Defined at <no location info> +| └ +| +`- ┌ + │ irred at T25709.hs:32:1-16, of type: c a + │ is an evidence variable bound by a let, depending on: [irred] + │ with scope: LocalScope T25709.hs:32:1-16 + │ bound at: T25709.hs:32:1-16 + │ Defined at <no location info> + └ + | + `- ┌ + │ irred at T25709.hs:32:1-16, of type: c a + │ is an evidence variable bound by a HsWrapper + │ with scope: LocalScope T25709.hs:32:1-16 + │ bound at: T25709.hs:32:1-16 + │ Defined at <no location info> + └ + ===================================== testsuite/tests/hiefile/should_run/all.T ===================================== @@ -8,4 +8,5 @@ test('HieVdq', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUti test('T23540', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('T23120', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) test('T24544', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) -test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) \ No newline at end of file +test('HieGadtConSigs', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) +test('T25709', [extra_run_opts('"' + config.libdir + '"'), extra_files(['TestUtils.hs'])], compile_and_run, ['-package ghc -fwrite-ide-info']) View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/dc5a2c6552f46e75c095c9d799c340… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/dc5a2c6552f46e75c095c9d799c340… 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
0 0
[Git][ghc/ghc][wip/T27557] 8 commits: testsuite: Don't crash on non-UTF-8 test output
by Simon Peyton Jones (@simonpj) 05 Aug '26

05 Aug '26
Simon Peyton Jones pushed to branch wip/T27557 at Glasgow Haskell Compiler / GHC Commits: 8fc6f882 by Simon Jakobi at 2026-08-05T14:53:41-04:00 testsuite: Don't crash on non-UTF-8 test output read_stdout, read_stderr_for, read_comp_stderr and read_diff decoded strictly (the first three with UTF-8, read_diff with the locale encoding), so a test emitting invalid UTF-8 (binary output, or a crash truncating a multi-byte character) raised UnicodeDecodeError and was reported as a framework failure instead of its actual result. Decode with errors='replace', like read_no_crs and safe_print. Assisted-by: Claude Fable 5 - - - - - 56534866 by Simon Jakobi at 2026-08-05T14:53:41-04:00 testsuite: Colorize the test summary, also in CI The summary headings were plain, and SUMMARY was colored unconditionally, so the escapes also ended up in the file written by --summary-file. Color is now decided per output sink via term_color.colored_if; see the comments in term_color. CI logs are not a tty, but GitLab's log viewer renders ANSI colors, so add --force-colors and pass it in .gitlab/ci.sh. Assisted-by: Claude Opus 5 - - - - - bceb541a by Simon Jakobi at 2026-08-05T14:53:42-04:00 testsuite: Repeat unexpected failure output in the summary Finding out why a test failed meant scrolling back through a possibly very long log to the point where the test ran. The summary now repeats the captured output of unexpected failures, before the statistics, so the most interesting part is at the end of the log (#16720). Output mismatches report their diff instead of the mismatching stream (see Note [Redundant output in test results]). The repeated output is bounded per stream, and skipped altogether beyond MAX_SUMMARY_OUTPUT_TESTS failure blocks. Tests failing identically in several ways share one block. Test results now report a source-relative directory, stable regardless of where the run was started from. Assisted-by: Claude Fable 5 - - - - - 2ab02c57 by Ben Gamari at 2026-08-05T14:54:24-04:00 base: Don't drop exception context in SomeException(toException) For reasons that are lost to time, the implementation of [CLC #200] that was merged inappropriately dropped `ExceptionContext` in the `toException` implementation given to `SomeException`. Fix this infelicity. [CLC #200]: https://github.com/haskell/core-libraries-committee/issues/200 - - - - - 126ce574 by Vladislav Zavialov at 2026-08-05T14:55:05-04:00 Test case for #20902 Starting with GHC 9.14.1 (the first major release to include 51e3ec83), and from point releases GHC 9.10.2 and GHC 9.12.3 (backports cc4470be68 and b30f25591e), all examples in this ticket are handled as expected. - - - - - b14d8d59 by Alan Zimmerman at 2026-08-05T14:55:46-04:00 EPA: Remove LocatedP, last use in WarningTxt The last step of removing LocatedP, by moving the AnnPragma for WarningTxt into its TTG extension point instead. This also allows us to remove LocatedP and SrcSpanAnnP - - - - - 70b58c8f by Vladislav Zavialov at 2026-08-05T14:56:27-04:00 Test cases for #18725 Starting with GHC 9.4 (the first release to include 268efcc9a4), the program in this ticket no longer panics. A standalone kind signature breaks the recursive loop, so the type constructor can be used in a kind within its own group. T18725a checks that this is accepted with the signature present, while T18725b confirms it is still rejected without it. - - - - - 6c991eed by Simon Peyton Jones at 2026-08-05T22:46:27+01:00 Fix three bugs related to required type args and INLINE pragmas * `GHC.Core.Opt.Arity.mkEtaForAllMCo` got the visibility flags back to front, leading to a Lint error (#27557) * The arity in an InlineSaturation is the VisArity not the Arity; the two can differ when we have "required" type arguments. This made the INLINE pragma argument counting go wrong in `makeCorePair` (#27590). * When a simple binding has a type signature, we take special path in `tcPolyCheck`, leading to an outer `AbsBinds` that has no dictionaries, even when the binding is in fact overloaded. That confused the inline-arity computation in `makeCorePair` (#27589). The latter two are fixed using the new function `GHC.HsToCore.Binds.findSatArity`. That actually simplifies the API of `makeCorePair`, which is nice. The first bug is fixed by swapping the visiblity flags in `GHC.Core.Opt.Arity.mkEtaForAllMCo` Getting the INLINE behaviour right led to some perf changes: * Runtime /halved/ on T7954 due to better specialisation * Compile time increased by 6% in T21839c because a bit more inlining happened, as it always should have done. * For some reason compile-time max-bytes-used dropped by 30% on T27336, but only on one build configuration Geometric mean effect on our compile time benchmarks is +0.1%. Metric Decrease: T27336 T7954 Metric Increase: T21839c - - - - - 43 changed files: - .gitlab/ci.sh - + changelog.d/T27455 - + changelog.d/T27557 - compiler/GHC/Builtin/Utils.hs - compiler/GHC/Core/Opt/Arity.hs - compiler/GHC/Hs/Decls.hs - compiler/GHC/Hs/Dump.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/HsToCore/Binds.hs - compiler/GHC/HsToCore/Match.hs - compiler/GHC/HsToCore/Ticks.hs - compiler/GHC/Iface/Syntax.hs - compiler/GHC/Iface/Warnings.hs - compiler/GHC/Parser.y - compiler/GHC/Parser/Annotation.hs - compiler/GHC/Tc/Gen/Bind.hs - compiler/GHC/Tc/Gen/Sig.hs - compiler/GHC/Types/Arity.hs - compiler/GHC/Types/InlinePragma.hs - compiler/GHC/Types/Var.hs - compiler/GHC/Unit/Module/Warnings.hs - libraries/base/changelog.md - libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs - testsuite/driver/runtests.py - testsuite/driver/term_color.py - testsuite/driver/testlib.py - testsuite/tests/ghc-e/should_fail/T18441fail7.stderr - testsuite/tests/ghc-e/should_run/ghc-e005.stderr - + testsuite/tests/saks/should_compile/T18725a.hs - testsuite/tests/saks/should_compile/all.T - + testsuite/tests/saks/should_fail/T18725b.hs - + testsuite/tests/saks/should_fail/T18725b.stderr - testsuite/tests/saks/should_fail/all.T - + testsuite/tests/simplCore/should_compile/T27589.hs - + testsuite/tests/simplCore/should_compile/T27589.stderr - + testsuite/tests/simplCore/should_compile/T27590.hs - + testsuite/tests/simplCore/should_compile/T27590.stderr - testsuite/tests/simplCore/should_compile/all.T - + testsuite/tests/th/T20902.hs - testsuite/tests/th/all.T - + testsuite/tests/typecheck/should_compile/T27557.hs - testsuite/tests/typecheck/should_compile/all.T - utils/check-exact/ExactPrint.hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5086333fc5b9df0754819851d40b66… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5086333fc5b9df0754819851d40b66… 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
0 0
[Git][ghc/ghc][wip/sjakobi/T27368-ppr] Cmm: print unreachable blocks under -dppr-debug (#27368)
by Simon Jakobi (@sjakobi) 05 Aug '26

05 Aug '26
Simon Jakobi pushed to branch wip/sjakobi/T27368-ppr at Glasgow Haskell Compiler / GHC Commits: ed4472ed by Simon Jakobi at 2026-08-05T23:17:22+02:00 Cmm: print unreachable blocks under -dppr-debug (#27368) Unreachable blocks linger in a CmmGraph's block map for most of the Cmm pipeline, but pprCmmGraph only ever printed the blocks reachable from the entry, so dumps looked consistent while the graph was not. Issues like #27368 were hard to debug due to this. pprCmmGraph now appends the stored-but-unreachable blocks under a "// unreachable blocks:" heading when -dppr-debug is on. See Note [unreachable blocks] in GHC.Cmm.Pipeline. Assisted-by: Claude Opus 5 - - - - - 8 changed files: - + changelog.d/T27368-ppr-unreachable-cmm-blocks.md - compiler/GHC/Cmm.hs - compiler/GHC/Cmm/Pipeline.hs - docs/users_guide/debugging.rst - testsuite/tests/cmm/should_compile/Makefile - + testsuite/tests/cmm/should_compile/T27368-ppr-debug.cmm - + testsuite/tests/cmm/should_compile/T27368-ppr-debug.stdout - testsuite/tests/cmm/should_compile/all.T Changes: ===================================== changelog.d/T27368-ppr-unreachable-cmm-blocks.md ===================================== @@ -0,0 +1,10 @@ +section: cmm +issues: #27368 +mrs: !16417 +synopsis: + Cmm dumps now show unreachable blocks under ``-dppr-debug`` +description: + Unreachable blocks stay in a Cmm graph's block map for most of the Cmm + pipeline, but ``-ddump-cmm-*`` only ever printed the blocks reachable from + the graph's entry. Adding ``-dppr-debug`` now appends the stored but + unreachable blocks, which makes bugs like #27368 visible in the dumps. ===================================== compiler/GHC/Cmm.hs ===================================== @@ -151,15 +151,28 @@ instance OutputableP Platform CmmGraph where toBlockMap :: CmmGraph -> LabelMap CmmBlock toBlockMap (CmmGraph {g_graph=GMany NothingO body NothingO}) = body +-- | Print the blocks reachable from the entry, in reverse postorder. +-- +-- Under @-dppr-debug@ the unreachable blocks stored in the graph are appended +-- too. See Note [unreachable blocks] in "GHC.Cmm.Pipeline". pprCmmGraph :: Platform -> CmmGraph -> SDoc pprCmmGraph platform g = text "{" <> text "offset" - $$ nest 2 (vcat $ map (pdoc platform) blocks) + $$ nest 2 (ppr_blocks blocks $$ unreachable) $$ text "}" - where blocks = revPostorder g - -- revPostorder has the side-effect of discarding unreachable code, - -- so pretty-printed Cmm will omit any unreachable blocks. This can - -- sometimes be confusing. + where + ppr_blocks :: [CmmBlock] -> SDoc + ppr_blocks = vcat . map (pdoc platform) + + blocks = revPostorder g + + unreachable = getPprDebug $ \debug -> + if not debug || mapNull dead_blocks + then empty + else text "// unreachable blocks:" + $$ nest 2 (ppr_blocks (mapElems dead_blocks)) + + dead_blocks = foldl' (\bs b -> mapDelete (entryLabel b) bs) (toBlockMap g) blocks revPostorder :: CmmGraph -> [CmmBlock] revPostorder g = {-# SCC "revPostorder" #-} ===================================== compiler/GHC/Cmm/Pipeline.hs ===================================== @@ -357,6 +357,7 @@ containing junk code. These aren't necessarily a problem, but removing them is good because it might save time in the native code generator later. +To make unreachable blocks visible in -ddump-cmm-* output, add -dppr-debug. -} dumpGraph :: Logger -> Platform -> Bool -> DumpFlag -> String -> CmmGraph -> IO () ===================================== docs/users_guide/debugging.rst ===================================== @@ -564,6 +564,11 @@ C-\- representation These flags dump various phases of GHC's C-\- pipeline. +Dumps of Cmm graphs print the blocks reachable from the entry, in reverse +post-order. To also show unreachable blocks, which can linger in the graph, +add :ghc-flag:`-dppr-debug`. These blocks are then listed under a +``// unreachable blocks:`` heading. + .. ghc-flag:: -ddump-cmm-verbose-by-proc :shortdesc: Show output from main C-\- pipeline passes (grouped by proc) :type: dynamic @@ -574,9 +579,6 @@ These flags dump various phases of GHC's C-\- pipeline. the chosen backend. Currently only the NCG backends runs additional passes ( :ghc-flag:`-ddump-opt-cmm` ). - Cmm dumps don't include unreachable blocks since we print - blocks in reverse post-order. - .. ghc-flag:: -ddump-cmm-verbose :shortdesc: Write output from main C-\- pipeline passes to files :type: dynamic ===================================== testsuite/tests/cmm/should_compile/Makefile ===================================== @@ -16,3 +16,16 @@ T16930: T23610: '$(TEST_HC)' $(TEST_HC_OPTS) T23610.cmm -S + +# The three seds below, in order: +# 1. Keep only the "Parsed Cmm" dump, since that is the one stage where the +# unreachable block still exists. +# 2. Rewrite goto targets: their label uniques survive -dsuppress-uniques +# (#21310). +# 3. Drop the "// CmmAssign"-style node annotations, which pprNode emits +# only on DEBUG compilers. +T27368-ppr-debug: + '$(TEST_HC)' $(TEST_HC_OPTS) -c -no-hs-main -ddump-cmm-verbose-by-proc -dppr-debug -dsuppress-uniques -dsuppress-ticks T27368-ppr-debug.cmm 2>&1 \ + | sed -n '/^==* Parsed Cmm/,/^ \}\]/p' \ + | sed 's/goto c[0-9A-Za-z]*/goto _lbl_/g' \ + | sed 's| *// Cmm[A-Za-z]*$$||' ===================================== testsuite/tests/cmm/should_compile/T27368-ppr-debug.cmm ===================================== @@ -0,0 +1,19 @@ +#include "Cmm.h" + +// The block "dead" is stored in the graph but no block branches to it, so it +// only shows up in Cmm dumps under -dppr-debug. +testUnreachable (W_ x) +{ + if (x > 0) { + goto live; + } + return (x); + +dead: + x = x + 42; + return (x); + +live: + x = x - 1; + return (x); +} ===================================== testsuite/tests/cmm/should_compile/T27368-ppr-debug.stdout ===================================== @@ -0,0 +1,27 @@ +==================== Parsed Cmm ==================== +[testUnreachable() { // [R1] + { info_tbls: [] + stack_info: arg_space: 8 + } + {offset + _lbl_: + __locVar_::I64 = R1; + if (__locVar_::I64 > 0) goto _lbl_; else goto _lbl_; + _lbl_: + goto _lbl_; + _lbl_: + __locVar_::I64 = __locVar_::I64 - 1; + R1 = __locVar_::I64; + call (P64[(old + 8)])(R1) args: 8, res: 0, upd: 8; + _lbl_: + goto _lbl_; + _lbl_: + R1 = __locVar_::I64; + call (P64[(old + 8)])(R1) args: 8, res: 0, upd: 8; + // unreachable blocks: + _lbl_: + __locVar_::I64 = __locVar_::I64 + 42; + R1 = __locVar_::I64; + call (P64[(old + 8)])(R1) args: 8, res: 0, upd: 8; + } + }] ===================================== testsuite/tests/cmm/should_compile/all.T ===================================== @@ -13,6 +13,11 @@ test('T20725', normal, compile, ['-package ghc']) test('T23610', normal, makefile_test, ['T23610']) test('T24224', [cmm_src, grep_errmsg(r'(F64.*);', [1]), only_ways(['normal'])], compile, ['-no-hs-main -ddump-cmm -dsuppress-all -dsuppress-uniques']) test('T24474', cmm_src, compile, ['-optc-g3']) +# -dppr-debug makes stored-but-unreachable blocks visible in Cmm dumps (#27368). +# Skipped on wordsize(32) targets, where the dump would say I32/P32, and on +# unregisterised builds, which print call targets with an extra load. +test('T27368-ppr-debug', [when(wordsize(32), skip), when(unregisterised(), skip)], + makefile_test, ['T27368-ppr-debug']) test('T24474-cmm-gets-c-opts', cmm_src, compile, ['-optc-DFOO']) test('T24474-cmm-opt-order', cmm_src, compile, ['-optc-DFOO ' '-optCmmP-UFOO ' View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ed4472ed8c1fff5a770e770889de31e… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/ed4472ed8c1fff5a770e770889de31e… 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
0 0
[Git][ghc/ghc][wip/az/exactprint-annotation-rationalisation] 31 commits: testsuite: Don't crash on non-UTF-8 test output
by Alan Zimmerman (@alanz) 05 Aug '26

05 Aug '26
Alan Zimmerman pushed to branch wip/az/exactprint-annotation-rationalisation at Glasgow Haskell Compiler / GHC Commits: 8fc6f882 by Simon Jakobi at 2026-08-05T14:53:41-04:00 testsuite: Don't crash on non-UTF-8 test output read_stdout, read_stderr_for, read_comp_stderr and read_diff decoded strictly (the first three with UTF-8, read_diff with the locale encoding), so a test emitting invalid UTF-8 (binary output, or a crash truncating a multi-byte character) raised UnicodeDecodeError and was reported as a framework failure instead of its actual result. Decode with errors='replace', like read_no_crs and safe_print. Assisted-by: Claude Fable 5 - - - - - 56534866 by Simon Jakobi at 2026-08-05T14:53:41-04:00 testsuite: Colorize the test summary, also in CI The summary headings were plain, and SUMMARY was colored unconditionally, so the escapes also ended up in the file written by --summary-file. Color is now decided per output sink via term_color.colored_if; see the comments in term_color. CI logs are not a tty, but GitLab's log viewer renders ANSI colors, so add --force-colors and pass it in .gitlab/ci.sh. Assisted-by: Claude Opus 5 - - - - - bceb541a by Simon Jakobi at 2026-08-05T14:53:42-04:00 testsuite: Repeat unexpected failure output in the summary Finding out why a test failed meant scrolling back through a possibly very long log to the point where the test ran. The summary now repeats the captured output of unexpected failures, before the statistics, so the most interesting part is at the end of the log (#16720). Output mismatches report their diff instead of the mismatching stream (see Note [Redundant output in test results]). The repeated output is bounded per stream, and skipped altogether beyond MAX_SUMMARY_OUTPUT_TESTS failure blocks. Tests failing identically in several ways share one block. Test results now report a source-relative directory, stable regardless of where the run was started from. Assisted-by: Claude Fable 5 - - - - - 2ab02c57 by Ben Gamari at 2026-08-05T14:54:24-04:00 base: Don't drop exception context in SomeException(toException) For reasons that are lost to time, the implementation of [CLC #200] that was merged inappropriately dropped `ExceptionContext` in the `toException` implementation given to `SomeException`. Fix this infelicity. [CLC #200]: https://github.com/haskell/core-libraries-committee/issues/200 - - - - - 126ce574 by Vladislav Zavialov at 2026-08-05T14:55:05-04:00 Test case for #20902 Starting with GHC 9.14.1 (the first major release to include 51e3ec83), and from point releases GHC 9.10.2 and GHC 9.12.3 (backports cc4470be68 and b30f25591e), all examples in this ticket are handled as expected. - - - - - b14d8d59 by Alan Zimmerman at 2026-08-05T14:55:46-04:00 EPA: Remove LocatedP, last use in WarningTxt The last step of removing LocatedP, by moving the AnnPragma for WarningTxt into its TTG extension point instead. This also allows us to remove LocatedP and SrcSpanAnnP - - - - - 70b58c8f by Vladislav Zavialov at 2026-08-05T14:56:27-04:00 Test cases for #18725 Starting with GHC 9.4 (the first release to include 268efcc9a4), the program in this ticket no longer panics. A standalone kind signature breaks the recursive loop, so the type constructor can be used in a kind within its own group. T18725a checks that this is accepted with the signature present, while T18725b confirms it is still rejected without it. - - - - - a6cbecf8 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Replace AnnPragma with individual types We introduced AnnPragma as a common type for all pragma usages wrapped in LocatedP / SrcSpanAnnP. Now that those are gone, and the AnnPragma moved into the TTG points for the given items, we can ensure that each carries only the annotations it needs. So we remove AnnPragma, and in its place bring in AnnCType AnnWarningTxt AnnOverlap AnnAnnDecl AnnPragSCC - - - - - 06bdd82a by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove LocatedE from WarningCategory - - - - - 6a48d848 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove LocateE from XCImport and XCExport - - - - - 405738d2 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove LocatedE from HsRecFields dot - - - - - c5072dd8 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove LocatedE completely, last usage for pats - - - - - fe5bcca7 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove AnnList (EpToken "where") usages This is moving toward removing the parameter from AnnList completely - - - - - 4e431d82 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA remove AnnList (EpToken "rec") usages - - - - - 397bf038 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove last parameterised AnnList usage (EpaLocation) Also remove the parameter - - - - - d0e1ec2f by Alan Zimmerman at 2026-08-05T20:20:25+01:00 TTG: Add extension points to BooleanFormula They are currently unused, but will be used for exact print annotations next - - - - - 256a1b78 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: Remove LocatedBC / SrcSpanBF - - - - - 08f4ec65 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPA: remove unused addTrailingAnnToL. Squash appropriately - - - - - e9ccb803 by Alan Zimmerman at 2026-08-05T20:20:25+01:00 EPS: Remove NoEpTok/NoEpUniTok, using an unhelpful SrcSpan instead Also introduce helper functions noEpTok and noEpUniTok to serve as simple replacements in code inserting an token annotation without location information. - - - - - f2188e0f by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA: Some haddock processing tweaks - - - - - eb34bf58 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 Some haddock exactprint tests - - - - - 9853521a by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA: When adding comments honour trailing anns - - - - - 97a795aa by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA: Uses Parsers.parseModule for exactprint tests This is the advertised way to parse for use for exact printing in the ghc-exactprint library, make sure we test using it. - - - - - 68f72547 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA Fix HsCmdDo exact print with comments TODO: add test based on proc-do-complex-four-out.hs - - - - - a12096b8 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA: Add comments about remaining Anno SrcSpan instances - - - - - 47f9d779 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA: First pass implementation of HsList, for ClassDecls Just as a straight list replacement to start with, no payload. This shows the scope and invasiveness of the initial change - - - - - beca14a1 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 WIP - - - - - 82797245 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 Enable ppr test for Haddock1. It currently fails - - - - - 0e1672da by Alan Zimmerman at 2026-08-05T21:19:04+01:00 WIP on removing NoEpAnn. Likely abandon - - - - - e6c52549 by Alan Zimmerman at 2026-08-05T21:19:04+01:00 EPA: Add an overview doc for exact printing - - - - - 6f49d29f by Simon Peyton Jones at 2026-08-05T21:19:04+01:00 Added an intro section - - - - - 99 changed files: - .gitlab/ci.sh - + ExactPrint.md - + changelog.d/T27455 - compiler/GHC/Builtin/Utils.hs - compiler/GHC/Core/Class.hs - compiler/GHC/CoreToIface.hs - compiler/GHC/Data/BooleanFormula.hs - compiler/GHC/Driver/Backpack.hs - compiler/GHC/Driver/Main/Interactive.hs - compiler/GHC/Hs.hs - compiler/GHC/Hs/Binds.hs - compiler/GHC/Hs/Decls.hs - compiler/GHC/Hs/Decls/Overlap.hs - compiler/GHC/Hs/Doc.hs - compiler/GHC/Hs/DocString.hs - compiler/GHC/Hs/Dump.hs - compiler/GHC/Hs/Expr.hs - compiler/GHC/Hs/Extension/Pass.hs - compiler/GHC/Hs/ImpExp.hs - compiler/GHC/Hs/Instances.hs - compiler/GHC/Hs/Pat.hs - compiler/GHC/Hs/Stats.hs - compiler/GHC/Hs/Utils.hs - compiler/GHC/Iface/Ext/Ast.hs - compiler/GHC/Iface/Syntax.hs - compiler/GHC/Iface/Warnings.hs - compiler/GHC/IfaceToCore.hs - compiler/GHC/Parser.y - compiler/GHC/Parser/Annotation.hs - compiler/GHC/Parser/PostProcess.hs - compiler/GHC/Parser/PostProcess/Haddock.hs - compiler/GHC/Rename/Module.hs - compiler/GHC/Rename/Pat.hs - compiler/GHC/Rename/Splice.hs - compiler/GHC/Tc/Module.hs - compiler/GHC/Tc/TyCl/Class.hs - compiler/GHC/Tc/Types/Origin.hs - compiler/GHC/ThToHs.hs - compiler/GHC/Types/ForeignCall.hs - compiler/GHC/Unit/Module/Warnings.hs - compiler/Language/Haskell/Syntax.hs - compiler/Language/Haskell/Syntax/Basic.hs - compiler/Language/Haskell/Syntax/BooleanFormula.hs - compiler/Language/Haskell/Syntax/Decls.hs - compiler/Language/Haskell/Syntax/Expr.hs - compiler/Language/Haskell/Syntax/Extension.hs - ghc/GHCi/UI.hs - libraries/base/changelog.md - libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs - testsuite/driver/runtests.py - testsuite/driver/term_color.py - testsuite/driver/testlib.py - testsuite/tests/ghc-api/T25121_status.stdout - testsuite/tests/ghc-api/exactprint/T22919.stderr - testsuite/tests/ghc-api/exactprint/Test20239.stderr - testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr - testsuite/tests/ghc-e/should_fail/T18441fail7.stderr - testsuite/tests/ghc-e/should_run/ghc-e005.stderr - 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/module/mod185.stderr - 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/DumpTypecheckedAst.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/printer/AnnotationNoListTuplePuns.stdout - + testsuite/tests/printer/Haddock1.hs - testsuite/tests/printer/Makefile - testsuite/tests/printer/T18791.stderr - testsuite/tests/printer/Test20297.stdout - testsuite/tests/printer/Test24533.stdout - testsuite/tests/printer/all.T - + testsuite/tests/saks/should_compile/T18725a.hs - testsuite/tests/saks/should_compile/all.T - + testsuite/tests/saks/should_fail/T18725b.hs - + testsuite/tests/saks/should_fail/T18725b.stderr - testsuite/tests/saks/should_fail/all.T - + testsuite/tests/th/T20902.hs - testsuite/tests/th/all.T - 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/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs - utils/haddock/haddock-api/src/Haddock/Convert.hs - utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs - utils/haddock/haddock-api/src/Haddock/Types.hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3b067e16ff3298b4caf62773fc04cc… -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3b067e16ff3298b4caf62773fc04cc… 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
0 0
  • ← Newer
  • 1
  • ...
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • ...
  • 64
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.