[Git][ghc/ghc][wip/T26315] 6 commits: Driver: substitute virtual Prim module in --make mode too
by Simon Peyton Jones (@simonpj) 02 Sep '25
by Simon Peyton Jones (@simonpj) 02 Sep '25
02 Sep '25
Simon Peyton Jones pushed to branch wip/T26315 at Glasgow Haskell Compiler / GHC
Commits:
6c78de2d by Sylvain Henry at 2025-09-01T08:46:19-04:00
Driver: substitute virtual Prim module in --make mode too
When we build ghc-internal with --make (e.g. with cabal-install), we
need to be careful to substitute the virtual interface file for
GHC.Internal.Prim:
- after code generation (we generate code for an empty module, so we get
an empty interface)
- when we try to reload its .hi file
- - - - -
26e0db16 by fendor at 2025-09-01T08:47:01-04:00
Expose Stack Annotation frames in IPE backtraces by default
When decoding the Haskell-native call stack and displaying the IPE information
for the stack frames, we print the `StackAnnotation` of the `AnnFrame` by default.
This means, when an exception is thrown, any intermediate stack annotations will
be displayed in the `IPE Backtrace`.
Example backtrace:
```
Exception: ghc-internal:GHC.Internal.Exception.ErrorCall:
Oh no!
IPE backtrace:
annotateCallStackIO, called at app/Main.hs:48:10 in backtrace-0.1.0.0-inplace-server:Main
annotateCallStackIO, called at app/Main.hs:46:13 in backtrace-0.1.0.0-inplace-server:Main
Main.handler (app/Main.hs:(46,1)-(49,30))
Main.liftIO (src/Servant/Server/Internal/Handler.hs:30:36-42)
Servant.Server.Internal.Delayed.runHandler' (src/Servant/Server/Internal/Handler.hs:27:31-41)
Control.Monad.Trans.Resource.runResourceT (./Control/Monad/Trans/Resource.hs:(192,14)-(197,18))
Network.Wai.Handler.Warp.HTTP1.processRequest (./Network/Wai/Handler/Warp/HTTP1.hs:195:20-22)
Network.Wai.Handler.Warp.HTTP1.processRequest (./Network/Wai/Handler/Warp/HTTP1.hs:(195,5)-(203,31))
Network.Wai.Handler.Warp.HTTP1.http1server.loop (./Network/Wai/Handler/Warp/HTTP1.hs:(141,9)-(157,42))
HasCallStack backtrace:
error, called at app/Main.hs:48:32 in backtrace-0.1.0.0-inplace-server:Main
```
The first two entries have been added by `annotateCallStackIO`, defined in `annotateCallStackIO`.
- - - - -
a1567efd by Sylvain Henry at 2025-09-01T23:01:35-04:00
RTS: rely less on Hadrian for flag setting (#25843)
Hadrian used to pass -Dfoo command-line flags directly to build the rts.
We can replace most of these flags with CPP based on cabal flags.
It makes building boot libraries with cabal-install simpler (cf #25843).
- - - - -
ca5b0283 by Sergey Vinokurov at 2025-09-01T23:02:23-04:00
Remove unnecessary irrefutable patterns from Bifunctor instances for tuples
Implementation of https://github.com/haskell/core-libraries-committee/issues/339
Metric Decrease:
mhu-perf
- - - - -
2da84b7a by sheaf at 2025-09-01T23:03:23-04:00
Only use active rules when simplifying rule RHSs
When we are simplifying the RHS of a rule, we make sure to only apply
rewrites from rules that are active throughout the original rule's
range of active phases.
For example, if a rule is always active, we only fire rules that are
themselves always active when simplifying the RHS. Ditto for inline
activations.
This is achieved by setting the simplifier phase to a range of phases,
using the new SimplPhaseRange constructor. Then:
1. When simplifying the RHS of a rule, or of a stable unfolding,
we set the simplifier phase to a range of phases, computed from
the activation of the RULE/unfolding activation, using the
function 'phaseFromActivation'.
The details are explained in Note [What is active in the RHS of a RULE?]
in GHC.Core.Opt.Simplify.Utils.
2. The activation check for other rules and inlinings is then:
does the activation of the other rule/inlining cover the whole
phase range set in sm_phase? This continues to use the 'isActive'
function, which now accounts for phase ranges.
On the way, this commit also moves the exact-print SourceText annotation
from the Activation datatype to the ActivationAnn type. This keeps the
main Activation datatype free of any extra cruft.
Fixes #26323
- - - - -
fe0cf55a by Simon Peyton Jones at 2025-09-02T15:51:09+01:00
Solve forall-constraints via an implication, again
In this earlier commit:
commit 953fd8f1dc080f1c56e3a60b4b7157456949be29
Author: Simon Peyton Jones <simon.peytonjones(a)gmail.com>
Date: Mon Jul 21 10:06:43 2025 +0100
Solve forall-constraints immediately, or not at all
I used a all-or-nothing strategy for quantified constraints
(aka forall-constraints). But alas that fell foul of #26315.
So this MR goes back to solving a quantified constraint by
turning it into an implication; UNLESS we are simplifying
constraints from a SPECIALISE pragma, in which case the
all-or-nothing strategy is great. See:
Note [Solving a Wanted forall-constraint]
Other stuff in this MR:
* TcSMode becomes a record of flags, rather than an enumeration
type; much nicer.
* Some fancy footwork to avoid error messages worsening again
(The above MR made them better; we want to retain that.)
See `GHC.Tc.Errors.Ppr.pprQCOriginExtra`.
- - - - -
81 changed files:
- compiler/GHC/Core/Opt/Pipeline/Types.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Parser.y
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Deriv/Utils.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Utils/Binary.hs
- hadrian/src/Settings/Packages.hs
- hie.yaml
- libraries/base/changelog.md
- libraries/base/src/Data/Bifunctor.hs
- libraries/ghc-experimental/src/GHC/Stack/Annotation/Experimental.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs
- + libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- libraries/ghc-internal/tests/stack-annotation/ann_frame002.stdout
- libraries/ghc-internal/tests/stack-annotation/ann_frame004.stdout
- rts/RtsMessages.c
- rts/RtsUtils.c
- rts/Trace.c
- testsuite/tests/backpack/should_fail/bkpfail11.stderr
- testsuite/tests/backpack/should_fail/bkpfail43.stderr
- testsuite/tests/deriving/should_fail/T12768.stderr
- testsuite/tests/deriving/should_fail/T1496.stderr
- testsuite/tests/deriving/should_fail/T5498.stderr
- testsuite/tests/deriving/should_fail/T7148.stderr
- testsuite/tests/deriving/should_fail/T7148a.stderr
- + testsuite/tests/driver/make-prim/GHC/Internal/Prim.hs
- + testsuite/tests/driver/make-prim/Makefile
- + testsuite/tests/driver/make-prim/Test.hs
- + testsuite/tests/driver/make-prim/Test2.hs
- + testsuite/tests/driver/make-prim/all.T
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/perf/compiler/T4007.stdout
- testsuite/tests/quantified-constraints/T19690.stderr
- testsuite/tests/quantified-constraints/T21006.stderr
- testsuite/tests/simplCore/should_compile/DsSpecPragmas.hs
- testsuite/tests/simplCore/should_compile/T15056.stderr
- testsuite/tests/simplCore/should_compile/T15445.stderr
- + testsuite/tests/simplCore/should_compile/T26323b.hs
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T26323.hs
- + testsuite/tests/simplCore/should_run/T26323.stdout
- testsuite/tests/simplCore/should_run/all.T
- testsuite/tests/typecheck/should_compile/T14434.hs
- testsuite/tests/typecheck/should_fail/T15801.stderr
- testsuite/tests/typecheck/should_fail/T22912.stderr
- 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/c3a4a7dfada9f184e74f53ac0af449…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c3a4a7dfada9f184e74f53ac0af449…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Simon Peyton Jones pushed to branch wip/T26315 at Glasgow Haskell Compiler / GHC
Commits:
c3a4a7df by Simon Peyton Jones at 2025-09-02T15:32:22+01:00
Wibbles
- - - - -
14 changed files:
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Gen/Sig.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types/Origin.hs
- testsuite/tests/deriving/should_fail/T12768.stderr
- testsuite/tests/deriving/should_fail/T1496.stderr
- testsuite/tests/deriving/should_fail/T5498.stderr
- testsuite/tests/deriving/should_fail/T7148.stderr
- testsuite/tests/deriving/should_fail/T7148a.stderr
- testsuite/tests/quantified-constraints/T19690.stderr
- testsuite/tests/quantified-constraints/T21006.stderr
- testsuite/tests/typecheck/should_fail/T15801.stderr
- testsuite/tests/typecheck/should_fail/T22912.stderr
Changes:
=====================================
compiler/GHC/Tc/Errors/Ppr.hs
=====================================
@@ -4197,17 +4197,6 @@ pprTcSolverReportMsg ctxt@(CEC {cec_encl = implics})
2 (text "Typeable" <+>
parens (ppr ty <+> dcolon <+> ppr (typeKind ty)))
- -- When we were originally trying to solve a quantified constraint like
- -- (forall a. Eq a => Eq (c a))
- -- add a note to say so, so the overall error looks like
- -- Cannot deduce Eq (c a)
- -- from (Eq a)
- -- when trying to solve (forall a. Eq a => Eq (c a))
- -- Without this, the error is very inscrutable
- | ScOrigin (IsQC pred orig) _ <- orig
- = hang (text "When trying to solve the quantified constraint")
- 2 (vcat [ ppr pred, pprCtOrigin orig ])
-
| otherwise
= empty
@@ -4264,7 +4253,7 @@ pprTcSolverReportMsg (CEC {cec_encl = implics}) (OverlappingInstances item match
-- simply report back the whole given
-- context. Accelerate Smart.hs showed this problem.
sep [ text "There exists a (perhaps superclass) match:"
- , nest 2 (vcat (pp_givens useful_givens))]
+ , nest 2 (vcat (pp_from_givens useful_givens))]
, ppWhen (null $ NE.tail matches) $
parens (vcat [ ppUnless (null tyCoVars) $
@@ -4395,6 +4384,7 @@ pprMismatchMsg ctxt
, mismatch_whenMatching = mb_match_txt
, mismatch_mb_same_occ = same_occ_info })
= vcat [ addArising (errorItemCtLoc item) msg
+ , pprQCOriginExtra item
, ea_extra
, maybe empty (pprWhenMatching ctxt) mb_match_txt
, maybe empty pprSameOccInfo same_occ_info ]
@@ -4447,9 +4437,10 @@ pprMismatchMsg ctxt
, teq_mismatch_actual = act -- the mis-match
, teq_mismatch_what = mb_thing
, teq_mb_same_occ = mb_same_occ })
- = addArising ct_loc $
- pprWithInvisibleBitsWhen ppr_invis_bits msg
- $$ maybe empty pprSameOccInfo mb_same_occ
+ = vcat [ addArising ct_loc $
+ pprWithInvisibleBitsWhen ppr_invis_bits msg
+ $$ maybe empty pprSameOccInfo mb_same_occ
+ , pprQCOriginExtra item ]
where
msg | Just (torc, rep) <- sORTKind_maybe exp
@@ -4565,45 +4556,55 @@ pprMismatchMsg ctxt
starts_with_vowel [] = False
pprMismatchMsg ctxt (CouldNotDeduce useful_givens (item :| others) mb_extra)
- = main_msg $$
- case supplementary of
- Left infos
- -> vcat (map (pprExpectedActualInfo ctxt) infos)
- Right other_msg
- -> other_msg
+ = vcat [ main_msg
+ , pprQCOriginExtra item
+ , ea_supplementary ]
where
main_msg
- | null useful_givens
- = addArising ct_loc (no_instance_msg <+> missing)
- | otherwise
- = vcat (addArising ct_loc (no_deduce_msg <+> missing)
- : pp_givens useful_givens)
-
- supplementary = case mb_extra of
- Nothing
- -> Left []
- Just (CND_Extra level ty1 ty2)
- -> mk_supplementary_ea_msg ctxt level ty1 ty2 orig
+ | null useful_givens = addArising ct_loc no_instance_msg
+ | otherwise = vcat ( addArising ct_loc no_deduce_msg
+ : pp_from_givens useful_givens)
+
+ ea_supplementary = case mb_extra of
+ Nothing -> empty
+ Just (CND_Extra level ty1 ty2) -> mk_supplementary_ea_msg ctxt level ty1 ty2 orig
+
ct_loc = errorItemCtLoc item
orig = ctLocOrigin ct_loc
wanteds = map errorItemPred (item:others)
no_instance_msg =
case wanteds of
- [wanted] | Just (tc, _) <- splitTyConApp_maybe wanted
- -- Don't say "no instance" for a constraint such as "c" for a type variable c.
- , isClassTyCon tc -> text "No instance for"
- _ -> text "Could not solve:"
+ [wanted] | -- Guard: don't say "no instance" for a constraint
+ -- such as "c" for a type variable c.
+ Just (tc, _) <- splitTyConApp_maybe wanted
+ , isClassTyCon tc
+ -> text "No instance for" <+> quotes (ppr wanted)
+ _ -> text "Could not solve:" <+> pprTheta wanteds
no_deduce_msg =
case wanteds of
- [_wanted] -> text "Could not deduce"
- _ -> text "Could not deduce:"
-
- missing =
- case wanteds of
- [wanted] -> quotes (ppr wanted)
- _ -> pprTheta wanteds
+ [wanted] -> text "Could not deduce" <+> quotes (ppr wanted)
+ _ -> text "Could not deduce:" <+> pprTheta wanteds
+
+pprQCOriginExtra :: ErrorItem -> SDoc
+-- When we were originally trying to solve a quantified constraint like
+-- (forall a. Eq a => Eq (c a))
+-- add a note to say so, so the overall error looks like
+-- Cannot deduce Eq (c a)
+-- from (Eq a)
+-- when trying to solve (forall a. Eq a => Eq (c a))
+-- Without this, the error is very inscrutable
+-- See (WFA3) in Note [Solving a Wanted forall-constraint],
+-- in GHC.Tc.Solver.Solve
+pprQCOriginExtra item
+ | ScOrigin (IsQC pred orig) _ <- orig
+ = hang (text "When trying to solve the quantified constraint")
+ 2 (vcat [ ppr pred, pprCtOrigin orig ])
+ | otherwise
+ = empty
+ where
+ orig = ctLocOrigin (errorItemCtLoc item)
pprKindMismatchMsg :: TypedThing -> Type -> Type -> SDoc
pprKindMismatchMsg thing exp act
@@ -4908,10 +4909,7 @@ pprWhenMatching ctxt (WhenMatching cty1 cty2 sub_o mb_sub_t_or_k) =
where
sub_t_or_k = mb_sub_t_or_k `orElse` TypeLevel
sub_whats = text (levelString sub_t_or_k) <> char 's'
- supplementary =
- case mk_supplementary_ea_msg ctxt sub_t_or_k cty1 cty2 sub_o of
- Left infos -> vcat $ map (pprExpectedActualInfo ctxt) infos
- Right msg -> msg
+ supplementary = mk_supplementary_ea_msg ctxt sub_t_or_k cty1 cty2 sub_o
pprTyVarInfo :: SolverReportErrCtxt -> TyVarInfo -> SDoc
pprTyVarInfo ctxt (TyVarInfo { thisTyVar = tv1, otherTy = mb_tv2, thisTyVarIsUntouchable = mb_implic })
@@ -5294,8 +5292,8 @@ usefulContext implics pred
implausible_info _ = False
-- Do not suggest adding constraints to an *inferred* type signature
-pp_givens :: [Implication] -> [SDoc]
-pp_givens givens
+pp_from_givens :: [Implication] -> [SDoc]
+pp_from_givens givens
= case givens of
[] -> []
(g:gs) -> ppr_given (text "from the context:") g
@@ -5465,13 +5463,15 @@ skolsSpan skol_tvs = foldr1WithDefault noSrcSpan combineSrcSpans (map getSrcSpan
**********************************************************************-}
mk_supplementary_ea_msg :: SolverReportErrCtxt -> TypeOrKind
- -> Type -> Type -> CtOrigin -> Either [ExpectedActualInfo] SDoc
+ -> Type -> Type -> CtOrigin -> SDoc
mk_supplementary_ea_msg ctxt level ty1 ty2 orig
| TypeEqOrigin { uo_expected = exp, uo_actual = act } <- orig
, not (ea_looks_same ty1 ty2 exp act)
- = mk_ea_msg ctxt Nothing level orig
+ = case mk_ea_msg ctxt Nothing level orig of
+ Left infos -> vcat $ map (pprExpectedActualInfo ctxt) infos
+ Right msg -> msg
| otherwise
- = Left []
+ = empty
ea_looks_same :: Type -> Type -> Type -> Type -> Bool
-- True if the faulting types (ty1, ty2) look the same as
=====================================
compiler/GHC/Tc/Gen/Sig.hs
=====================================
@@ -976,6 +976,8 @@ tcSpecPrag poly_id (SpecSigE nm rule_bndrs spec_e inl)
tcInferRho spec_e
-- (2) Solve the resulting wanteds
+ -- When doing so, switch on `tcsmFullySolveQCIs`; see (WFA4) in
+ -- Note [Solving a Wanted forall-constraint] in GHC.Tc.Solver.Solve
; ev_binds_var <- newTcEvBinds
; spec_e_wanted <- setTcLevel rhs_tclvl $
runTcSWithEvBinds ev_binds_var $
=====================================
compiler/GHC/Tc/Solver/Monad.hs
=====================================
@@ -908,7 +908,7 @@ data TcSMode
, tcsmSkipOverlappable :: Bool
-- ^ Do not select an OVERLAPPABLE instance
, tcsmFullySolveQCIs :: Bool
- -- ^ Fully solve all constraints, without using local Givens
+ -- ^ Fully solve quantified constraints
}
vanillaTcSMode :: TcSMode
@@ -1281,7 +1281,8 @@ tryShortCutTcS :: TcS Bool -> TcS Bool
-- Use only by the short-cut solver;
-- see Note [Shortcut solving] in GHC.Tc.Solver.Dict
tryShortCutTcS (TcS thing_inside)
- = TcS $ \ env@(TcSEnv { tcs_inerts = inerts_var
+ = TcS $ \ env@(TcSEnv { tcs_mode = mode
+ , tcs_inerts = inerts_var
, tcs_ev_binds = old_ev_binds_var }) ->
do { -- Initialise a fresh inert set, with no Givens and no Wanteds
-- (i.e. empty `inert_cans`)
@@ -1297,7 +1298,7 @@ tryShortCutTcS (TcS thing_inside)
; new_wl_var <- TcM.newTcRef emptyWorkList
; new_ev_binds_var <- TcM.cloneEvBindsVar old_ev_binds_var
- ; let nest_env = env { tcs_mode = vanillaTcSMode { tcsmSkipOverlappable = True }
+ ; let nest_env = env { tcs_mode = mode { tcsmSkipOverlappable = True }
, tcs_ev_binds = new_ev_binds_var
, tcs_inerts = new_inert_var
, tcs_worklist = new_wl_var }
=====================================
compiler/GHC/Tc/Solver/Solve.hs
=====================================
@@ -124,12 +124,10 @@ simplify_loop n limit definitely_redo_implications
-- Any insoluble constraints are in 'simples' and so get rewritten
-- See Note [Rewrite insolubles] in GHC.Tc.Solver.InertSet
- ; mode <- getTcSMode
- ; extras :: Bag (Either Ct Implication) <- mapMaybeBagM (solveWantedQCI mode) simples1
- ; let simples' :: Cts -- simples1 are all Wanteds
- implics_from_qcis :: Bag Implication
- (simples', implics_from_qcis) = partitionBagWith id extras
+ -- Now try to solve any Wanted QCInsts in `simples1`
+ ; (simples', implics_from_qcis) <- solveWantedQCIs simples1
+ -- Next, solve implications from wc_impl
; implics' <- if not definitely_redo_implications -- See Note [Superclass iteration]
&& unifs1 == 0 -- for this conditional
then return implics
@@ -1319,53 +1317,22 @@ and discharge df thus:
df = /\ab. \g1 g2. let <binds> in d
where <binds> is filled in by solving the implication constraint.
-What we actually do is:
-* In `solveForAll` we see if we have an identical quantified constraint
- to solve it (tryInertQCs), and then just add it to `inert_qcis :: [QCInst]`
-* In the main solver loop, `GHC.Tc.Solver.Solve.simplify_loop`,
- - We attempt to solve the `wc_simple` constraints with `solveSimpleWanteds`
- - we grab grab any unsolved Wanted quantified constraints
- from that attempt; they are all `QCInst` constraints.
- - we turn those Wanted `QCInst` constraints into `Implication`s,
- using `wantedQciToImplic`.
- - we add them to `wc_implic` and do `solveImplications`
-
-We do not /actually/ emit an implication to solve later. Rather we
-try to solve it completely immediately using `trySolveImplication`
- - If successful, we can build evidence
- - If unsuccessful, we abandon the attempt and add the unsolved
- forall-constraint to the inert set.
-
-There are several reasons for this "solve immediately" approach
+What we actually do is this:
-* It saves quite a bit of plumbing, tracking the emitted implications for
- later solving; and the evidence would have to contain as-yet-incomplte
- bindings which complicates tracking of unused Givens.
-
-* We get better error messages, about failing to solve, say
- (forall a. a->a) ~ (forall b. b->Int)
-
-* Consider
- f :: forall f a. (Ix a, forall x. Eq x => Eq (f x)) => a -> f a
- {-# SPECIALISE f :: forall f. (forall x. Eq x => Eq (f x)) => Int -> f Int #-}
- This SPECIALISE is treated like an expression with a type signature, so
- we instantiate the constraints, simplify them and re-generalise. From the
- instantiation we get [W] d :: (forall x. Eq a => Eq (f x))
- and we want to generalise over that. We do not want to attempt to solve it
- and then get stuck, and emit an error message. If we can't solve it, better
- to leave it alone.
+* In `solveForAll` we see if we have an identical quantified constraint
+ to solve it (using tryInertQCs), and then just add it to `inert_qcis :: [QCInst]`
+ See Note [Solving Wanted QCs from Given QCs]
- We still need to simplify quantified constraints that can be
- /fully solved/ from instances, otherwise we would never be able to
- specialise them away. Example: {-# SPECIALISE f @[] @a #-}.
+* In the main solver loop, `GHC.Tc.Solver.Solve.simplify_loop`:
- This last point is a big one: it was the immediate driver for moving to
- the "solve immediately" approach.
+ - We attempt to solve the `wc_simple` constraints with `solveSimpleWanteds`
+ Unsolved quantified constraints just accumulate in the `inert_qcis` field
+ of the `InertSet`.
-You might worry about the wasted work from failed attempts to fully-solve, but
-it is seldom repeated (because the constraint solver seldom iterates much).
+ - Then we use `solveWantedQCIs` to solve any quantified constraints. It usually
+ turns the `QCInst` into an `Implication`; but not invariably (WFA4)
-There are some tricky corners though:
+Wrinkles:
(WFA1) We can take a more straightforward path when there is a matching Given, e.g.
[W] dg :: forall c d. (Eq c, Ord d) => C x c d
@@ -1386,16 +1353,38 @@ There are some tricky corners though:
* Give the Givens a CtOrigin of (GivenOrigin (InstSkol IsQC head_size))
* Give the Wanted a CtOrigin of (ScOrigin IsQC NakedSc)
- Both of these things are done in solveForAll. Now the mechanism described
+ Both of these things are done in `solveWantedQCI`. Now the mechanism described
in Note [Solving superclass constraints] in GHC.Tc.TyCl.Instance takes over.
-(WFA3) When inferring an appropriate context for a `deriving` instance, we
- really /do/ want to generate an implication, and perhaps leave it half-solved,
- from where we might then gather unsolved class constraints (via
- `approximateWC` called in GHC.Tc.Deriv.Infer.simplifyDeriv). Rather than
- have a complicated special solver mode, we simply generate an /implication/
- in the first place, in GHC.Tc.Deriv.Utils.emitPredSpecConstraints.
- See Note [Inferred contexts from method constraints] in GHC.Tc.Deriv.Infer
+(WFA3) Error messages. Suppose we are trying to solve the quantified constraint
+ forall a. Eq a => Eq (c a)
+ We don't just want to say "No instance for Eq (c a)". It /really/ helps to
+ say what quantified constraint we were trying to solve.
+
+ So the `IsQC` origin carries that info, and `GHC.Tc.Errors.Ppr.pprQCOriginExtra`
+ prints the extra info.
+
+(WFA4) Consider
+ f :: forall f a. (Ix a, forall x. Eq x => Eq (f x)) => a -> f a
+ {-# SPECIALISE f :: forall f. (forall x. Eq x => Eq (f x)) => Int -> f Int #-}
+ This SPECIALISE is treated like an expression with a type signature, so
+ we instantiate the constraints, simplify them and re-generalise. From the
+ instantiation we get [W] d :: (forall x. Eq a => Eq (f x))
+ and we want to generalise over that. We do not want to attempt to solve it
+ and then get stuck, and emit an error message. If we can't solve it, it is
+ much, much better to leave it alone.
+
+ We still need to simplify quantified constraints that can be /fully solved/
+ from instances, otherwise we would never be able to specialise them
+ away. Example: {-# SPECIALISE f @[] @a #-}. So:
+
+ * The constraint solver has a mode flag `tcsmFullySolveQCIs` that says
+ "fully solve quantified constraint, or leave them alone
+ * When simplifying constraints in a SPECIALISE pragma, we switch on this
+ flag (see `GHC.Tc.Gen.Sig.tcSpecPrag`, the `SpecSigE` case).
+
+ You might worry about the wasted work from failed attempts to fully-solve, but
+ it is seldom repeated (because the constraint solver seldom iterates much).
Note [Solving Wanted QCs from Given QCs]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1505,13 +1494,23 @@ try_inert_qcs (QCI { qci_ev = ev_w }) inerts =
| otherwise
= Nothing
+solveWantedQCIs :: Cts -> TcS (Cts, Bag Implication)
+solveWantedQCIs wanteds
+ = do { mode <- getTcSMode
+ ; bag_of_eithers <- mapBagM (solveWantedQCI mode) wanteds
+ -- bag_of_eithers :: Bag (Either Ct Implication)
+ ; return (partitionBagWith id bag_of_eithers) }
+
solveWantedQCI :: TcSMode
-> Ct -- Definitely a Wanted
- -> TcS (Maybe (Either Ct Implication))
--- Try to solve a quantified constraint.
--- In TcSChortCut mode, insist on solving it fully or not at all
+ -> TcS (Either Ct Implication)
+-- Try to solve a quantified constraint, `ct`
-- Returns
--- No-op on all Cts other than CQuantCan
+-- (Left ct) if `ct` is not a quantified constraint
+-- (Right implic) if we can solve a quantified constraint `ct` by creating
+-- an implication and fully or partly solving it
+-- (Left ct) for a quantified constraint that can't be /fully solved/,
+-- but mode is tcsmFullySolveQCIs
-- See Note [Solving a Wanted forall-constraint]
solveWantedQCI mode ct@(CQuantCan (QCI { qci_ev = ev, qci_tvs = tvs
, qci_theta = theta, qci_body = body_pred }))
@@ -1543,7 +1542,8 @@ solveWantedQCI mode ct@(CQuantCan (QCI { qci_ev = ev, qci_tvs = tvs
; newWantedNC loc' rewriters inst_pred }
; ev_binds_var <- TcS.newTcEvBinds
- ; let imp = (implicationPrototype (ctLocEnv loc))
+ ; let imp :: Implication
+ imp = (implicationPrototype (ctLocEnv loc))
{ ic_tclvl = lvl
, ic_skols = skol_tvs
, ic_given = given_ev_vars
@@ -1558,7 +1558,7 @@ solveWantedQCI mode ct@(CQuantCan (QCI { qci_ev = ev, qci_tvs = tvs
, not (isSolvedStatus (ic_status imp'))
-> -- Not fully solved, but mode says that we must fully
-- solve quantified constraints; so abandon the attempt
- return (Just (Left ct))
+ return (Left ct)
| otherwise
-> -- Record evidence and return residual implication
@@ -1570,14 +1570,14 @@ solveWantedQCI mode ct@(CQuantCan (QCI { qci_ev = ev, qci_tvs = tvs
, et_binds = TcEvBinds ev_binds_var
, et_body = wantedCtEvEvId wanted_ev }
- ; return (Just (Right imp')) }
+ ; return (Right imp') }
}
| otherwise -- A Given QCInst
= pprPanic "wantedQciToImplic: found a Given QCI" (ppr ct)
-- No-op on all Ct's other than CQuantCan
-solveWantedQCI _ ct = return (Just (Left ct))
+solveWantedQCI _ ct = return (Left ct)
{-
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -910,8 +910,9 @@ ppr_ct_origin herald (ScOrigin IsClsInst nkd)
ppr_ct_origin _herald (ScOrigin (IsQC pred orig) nkd)
= vcat [ whenPprDebug (text "IsQC" <> braces (text "sc-origin:" <> ppr nkd) <+> ppr pred)
- , ppr_ct_origin (text "arising (via a quantified constraint) from") orig ]
- -- Just print `orig`, with a new herald
+ , hang (text "arising (via a quantified constraint) from") 2 (pprCtO orig) ]
+ -- Print `orig` briefly with pprCtO. We'll print it more voluminously later.
+ -- See GHC.Tc.Errors.Ppr.pprQCOriginExtra
ppr_ct_origin herald (NonLinearPatternOrigin reason pat)
= hang (herald <+> text "a non-linear pattern" <+> quotes (ppr pat))
=====================================
testsuite/tests/deriving/should_fail/T12768.stderr
=====================================
@@ -1,13 +1,12 @@
T12768.hs:9:33: error: [GHC-39999]
• Could not deduce ‘D [a]’
- arising from the coercion of the method ‘op’
- from type ‘D [a] => [a] -> [a]’ to type ‘D (N a) => N a -> N a’
+ arising (via a quantified constraint) from a derived method
from the context: C a
bound by the deriving clause for ‘C (N a)’ at T12768.hs:9:33
- or from: D (N a)
- bound by the method declaration for op at T12768.hs:9:33
- Possible fix:
- use a standalone 'deriving instance' declaration,
- so you can specify the instance context yourself
+ or from: D (N a) bound by a quantified constraint at T12768.hs:9:33
+ When trying to solve the quantified constraint
+ D (N a) => (Coercible ([a] -> [a]) (N a -> N a), D [a])
+ arising from the coercion of the method ‘op’
+ from type ‘D [a] => [a] -> [a]’ to type ‘D (N a) => N a -> N a’
• When deriving the instance for (C (N a))
=====================================
testsuite/tests/deriving/should_fail/T1496.stderr
=====================================
@@ -1,6 +1,9 @@
T1496.hs:10:32: error: [GHC-18872]
• Couldn't match representation of type: c Int
with that of: c Moo
+ arising (via a quantified constraint) from a derived method
+ When trying to solve the quantified constraint
+ forall (c :: * -> *). Coercible (c Int -> c Int) (c Int -> c Moo)
arising from the coercion of the method ‘isInt’
from type ‘forall (c :: * -> *). c Int -> c Int’
to type ‘forall (c :: * -> *). c Int -> c Moo’
=====================================
testsuite/tests/deriving/should_fail/T5498.stderr
=====================================
@@ -1,6 +1,10 @@
T5498.hs:30:39: error: [GHC-18872]
• Couldn't match representation of type: c a
with that of: c (Down a)
+ arising (via a quantified constraint) from a derived method
+ When trying to solve the quantified constraint
+ forall (c :: * -> *).
+ Coercible (c a -> c Int) (c (Down a) -> c Int)
arising from the coercion of the method ‘intIso’
from type ‘forall (c :: * -> *). c a -> c Int’
to type ‘forall (c :: * -> *). c (Down a) -> c Int’
=====================================
testsuite/tests/deriving/should_fail/T7148.stderr
=====================================
@@ -1,8 +1,14 @@
T7148.hs:27:40: error: [GHC-25897]
• Couldn't match type ‘b’ with ‘Tagged a b’
- arising from the coercion of the method ‘iso1’
- from type ‘forall b1. SameType () b1 -> SameType b b1’
- to type ‘forall b1. SameType () b1 -> SameType (Tagged a b) b1’
+ arising (via a quantified constraint) from a derived method
+ When trying to solve the quantified constraint
+ forall b1.
+ Coercible
+ (SameType b1 () -> SameType b1 b)
+ (SameType b1 () -> SameType b1 (Tagged a b))
+ arising from the coercion of the method ‘iso2’
+ from type ‘forall b1. SameType b1 () -> SameType b1 b’
+ to type ‘forall b1. SameType b1 () -> SameType b1 (Tagged a b)’
‘b’ is a rigid type variable bound by
the deriving clause for ‘IsoUnit (Tagged a b)’
at T7148.hs:27:40-46
@@ -10,9 +16,15 @@ T7148.hs:27:40: error: [GHC-25897]
T7148.hs:27:40: error: [GHC-25897]
• Couldn't match type ‘b’ with ‘Tagged a b’
- arising from the coercion of the method ‘iso2’
- from type ‘forall b1. SameType b1 () -> SameType b1 b’
- to type ‘forall b1. SameType b1 () -> SameType b1 (Tagged a b)’
+ arising (via a quantified constraint) from a derived method
+ When trying to solve the quantified constraint
+ forall b1.
+ Coercible
+ (SameType () b1 -> SameType b b1)
+ (SameType () b1 -> SameType (Tagged a b) b1)
+ arising from the coercion of the method ‘iso1’
+ from type ‘forall b1. SameType () b1 -> SameType b b1’
+ to type ‘forall b1. SameType () b1 -> SameType (Tagged a b) b1’
‘b’ is a rigid type variable bound by
the deriving clause for ‘IsoUnit (Tagged a b)’
at T7148.hs:27:40-46
=====================================
testsuite/tests/deriving/should_fail/T7148a.stderr
=====================================
@@ -1,12 +1,17 @@
T7148a.hs:19:50: error: [GHC-10283]
• Couldn't match representation of type ‘b’
with that of ‘Result a b’
+ arising (via a quantified constraint) from a derived method
+ When trying to solve the quantified constraint
+ forall b.
+ Coercible
+ (Proxy b -> a -> Result a b) (Proxy b -> IS_NO_LONGER a -> b)
arising from the coercion of the method ‘coerce’
from type ‘forall b. Proxy b -> a -> Result a b’
to type ‘forall b.
Proxy b -> IS_NO_LONGER a -> Result (IS_NO_LONGER a) b’
‘b’ is a rigid type variable bound by
- the method declaration for coerce
+ a quantified constraint
at T7148a.hs:19:50-56
• When deriving the instance for (Convert (IS_NO_LONGER a))
=====================================
testsuite/tests/quantified-constraints/T19690.stderr
=====================================
@@ -1,5 +1,11 @@
T19690.hs:12:16: error: [GHC-05617]
- • Could not solve: ‘Hold c => c’ arising from a use of ‘go’
+ • Could not deduce ‘c’
+ arising (via a quantified constraint) from a use of ‘go’
+ from the context: Hold c
+ bound by a quantified constraint at T19690.hs:12:16-17
+ When trying to solve the quantified constraint
+ Hold c => c
+ arising from a use of ‘go’
• In the expression: go
In an equation for ‘anythingDict’:
anythingDict
@@ -7,4 +13,6 @@ T19690.hs:12:16: error: [GHC-05617]
where
go :: (Hold c => c) => Dict c
go = Dict
+ • Relevant bindings include
+ anythingDict :: Dict c (bound at T19690.hs:12:1)
=====================================
testsuite/tests/quantified-constraints/T21006.stderr
=====================================
@@ -1,7 +1,11 @@
T21006.hs:14:10: error: [GHC-05617]
- • Could not solve: ‘forall b (c :: Constraint).
- (Determines b, Determines c) =>
- c’
+ • Could not deduce ‘c’
+ arising (via a quantified constraint) from
+ the superclasses of an instance declaration
+ from the context: (Determines b, Determines c)
+ bound by a quantified constraint at T21006.hs:14:10-15
+ When trying to solve the quantified constraint
+ forall b (c :: Constraint). (Determines b, Determines c) => c
arising from the superclasses of an instance declaration
• In the instance declaration for ‘OpCode’
=====================================
testsuite/tests/typecheck/should_fail/T15801.stderr
=====================================
@@ -1,6 +1,9 @@
-T15801.hs:52:10: error: [GHC-05617]
- • Could not solve: ‘forall (op_a :: Op (*)) (b :: Op (*)).
- op_a -#- b’
+T15801.hs:52:10: error: [GHC-18872]
+ • Couldn't match representation of type: UnOp op_a -> UnOp b
+ with that of: op_a --> b
+ arising (via a quantified constraint) from the superclasses of an instance declaration
+ When trying to solve the quantified constraint
+ forall (op_a :: Op (*)) (b :: Op (*)). op_a -#- b
arising from the superclasses of an instance declaration
• In the instance declaration for ‘OpRíki (Op (*))’
=====================================
testsuite/tests/typecheck/should_fail/T22912.stderr
=====================================
@@ -1,6 +1,15 @@
-T22912.hs:17:16: error: [GHC-05617]
- • Could not solve: ‘Exactly (Implies c) => Implies c’
+T22912.hs:17:16: error: [GHC-39999]
+ • Could not deduce ‘Implies c’
+ arising (via a quantified constraint) from a use of ‘go’
+ from the context: Exactly (Implies c)
+ bound by a quantified constraint at T22912.hs:17:16-17
+ When trying to solve the quantified constraint
+ Exactly (Implies c) => Implies c
arising from a use of ‘go’
+ Possible fix:
+ add (Implies c) to the context of
+ the type signature for:
+ anythingDict :: forall (c :: Constraint). Dict c
• In the expression: go
In an equation for ‘anythingDict’:
anythingDict
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c3a4a7dfada9f184e74f53ac0af449a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c3a4a7dfada9f184e74f53ac0af449a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/backports-9.14] 3 commits: Revert "STM: don't create a transaction in the rhs of catchRetry# (#26028)"
by Ben Gamari (@bgamari) 02 Sep '25
by Ben Gamari (@bgamari) 02 Sep '25
02 Sep '25
Ben Gamari pushed to branch wip/backports-9.14 at Glasgow Haskell Compiler / GHC
Commits:
4d8eec9a by Ben Gamari at 2025-09-02T08:58:18-04:00
Revert "STM: don't create a transaction in the rhs of catchRetry# (#26028)"
This appears to have been the cause of runtime crashes (#26291).
This reverts commit 712da3565dcdeea17f3d1fc71e026839ede56533.
- - - - -
0980f3d6 by Ben Gamari at 2025-09-02T08:58:53-04:00
users-guide/relnotes: More stylistic fixes
- - - - -
5f9c0b62 by Ben Gamari at 2025-09-02T08:58:53-04:00
users-guide: Various release notes additions
- - - - -
7 changed files:
- docs/users_guide/9.14.1-notes.rst
- rts/PrimOps.cmm
- rts/RaiseAsync.c
- rts/STM.c
- − testsuite/tests/lib/stm/T26028.hs
- − testsuite/tests/lib/stm/T26028.stdout
- − testsuite/tests/lib/stm/all.T
Changes:
=====================================
docs/users_guide/9.14.1-notes.rst
=====================================
@@ -25,6 +25,14 @@ Language
This deprecation is controlled by the newly introduced ``-Wdeprecated-pragmas``
flag in ``-Wdefault``.
+* Visible ``GADT`` syntax can now be used in GADT data constructors (:ghc-ticket:`25127`) ::
+
+ data KindVal a where
+ K :: forall k.
+ forall (a::k) -> -- now allowed!
+ k ->
+ KindVal a
+
* ``-Wincomplete-record-selectors`` is now part of `-Wall`, as specified
by `GHC Proposal 516: add warning for incomplete record selectors <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0516-i…>`_.
Hence, if a library is compiled with ``-Werror``, compilation may now fail. Solution: fix the library.
@@ -52,7 +60,7 @@ Language
That will break the combination of :extension:`OverloadedRecordUpdate` with :extension:`RebindableSyntax`.
-* Multiline strings are now accepted in foreign imports. (#25157)
+* Multiline strings are now accepted in ``foreign import``\ s. (#25157)
* GHC now does a better job at inferring types in calls to ``coerce``: instead of
complaining about ambiguous type variables, GHC will consider that such type
@@ -73,7 +81,7 @@ Language
* The ``-Wdata-kinds-tc`` warning has been deprecated, and the use of promoted
data types in kinds is now an error (rather than a warning) unless the
:extension:`DataKinds` extension is enabled. For example, the following code
- will be rejected unless :extension:`DataKinds` is on:
+ will be rejected unless :extension:`DataKinds` is on: ::
import Data.Kind (Type)
import GHC.TypeNats (Nat)
@@ -99,6 +107,9 @@ Language
See :ref:`visible-forall-in-gadts` for details.
+- Explicit level import support, allowing ``import`` declarations to explicitly
+ state which compilation stages they are are visible to.
+
Compiler
~~~~~~~~
@@ -143,20 +154,27 @@ Compiler
were accessed using the generated record selector functions, marking the fields
as covered in coverage reports (:ghc-ticket:`17834`).
-- SIMD support in the X86 native code generator has been extended with 128-bit
+- SIMD support in the x86 native code generator has been extended with 128-bit
integer operations. Also, ``shuffleFloatX4#`` and ``shuffleDoubleX2#`` no longer
require ``-mavx``.
+- Initial native code generator support for the LoongArch CPU architecture.
+
+
GHCi
~~~~
-- :ghci-cmd:`:info` now outputs type declarations with @-binders that are
+- Multiple home unit support in GHCi
+
+- :ghci-cmd:`:info` now outputs type declarations with ``@``-binders that are
considered semantically significant. See the documentation for :ghci-cmd:`:info`
itself for a more detailed explanation.
- GHCi errors and warnings now have their own numeric error codes that are
displayed alongside the error.
+- Many performance and correctness improvements in the bytecode interpreter.
+
Runtime system
~~~~~~~~~~~~~~
@@ -176,40 +194,40 @@ Cmm
``ghc`` library
~~~~~~~~~~~~~~~
-* The `UnknownDiagnostic` constructor now takes an additional type argument
+* The ``UnknownDiagnostic`` constructor now takes an additional type argument
for the type of hints corresponding to the diagnostic, and an additional
value-level argument used for existential wrapping of the hints of the inner
diagnostic.
* Changes to the HPT and HUG interface:
- - `addToHpt` and `addListToHPT` were moved from `GHC.Unit.Home.ModInfo` to `GHC.Unit.Home.PackageTable` and deprecated in favour of `addHomeModInfoToHpt` and `addHomeModInfosToHpt`.
- - `UnitEnvGraph` and operations `unitEnv_lookup_maybe`, `unitEnv_foldWithKey, `unitEnv_singleton`, `unitEnv_adjust`, `unitEnv_insert`, `unitEnv_new` were moved from `GHC.Unit.Env` to `GHC.Unit.Home.Graph`.
- - The HomePackageTable (HPT) is now exported from `GHC.Unit.Home.PackageTable`,
+ - ``addToHpt`` and ``addListToHPT`` were moved from ``GHC.Unit.Home.ModInfo`` to ``GHC.Unit.Home.PackageTable`` and deprecated in favour of ``addHomeModInfoToHpt`` and ``addHomeModInfosToHpt``.
+ - ``UnitEnvGraph`` and operations ``unitEnv_lookup_maybe``, ``unitEnv_foldWithKey, ``unitEnv_singleton``, ``unitEnv_adjust``, ``unitEnv_insert``, ``unitEnv_new`` were moved from ``GHC.Unit.Env`` to ``GHC.Unit.Home.Graph``.
+ - The HomePackageTable (HPT) is now exported from ``GHC.Unit.Home.PackageTable``,
and is now backed by an IORef to avoid by construction very bad memory leaks.
This means the API to the HPT now is for the most part in IO. For instance,
- `emptyHomePackageTable` and `addHomeModInfoToHpt` are now in IO.
- - `mkHomeUnitEnv` was moved to `GHC.Unit.Home.PackageTable`, and now takes two
- extra explicit arguments. To restore previous behaviour, pass `emptyUnitState`
- and `Nothing` as the first two arguments additionally.
- - `hugElts` was removed. Users should prefer `allUnits` to get the keys of the
- HUG (the typical use case), or `traverse` or `unitEnv_foldWithKey` in other
+ ``emptyHomePackageTable`` and ``addHomeModInfoToHpt`` are now in IO.
+ - ``mkHomeUnitEnv`` was moved to ``GHC.Unit.Home.PackageTable``, and now takes two
+ extra explicit arguments. To restore previous behaviour, pass ``emptyUnitState``
+ and ``Nothing`` as the first two arguments additionally.
+ - ``hugElts`` was removed. Users should prefer ``allUnits`` to get the keys of the
+ HUG (the typical use case), or ``traverse`` or ``unitEnv_foldWithKey`` in other
cases.
-* Changes to `Language.Haskell.Syntax.Expr`
+* Changes to ``Language.Haskell.Syntax.Expr``
- - The `ParStmtBlock` list argument of the `ParStmt` constructor of `StmtLR` is now `NonEmpty`.
+ - The ``ParStmtBlock`` list argument of the ``ParStmt`` constructor of ``StmtLR`` is now ``NonEmpty``.
-* As part of the implementation of `GHC proposal 493 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0493-s…>`_,
- the `SpecSig` constructor of `Sig` has been deprecated. It is replaced by
- the constructor `SpecSigE` which supports expressions at the head, rather than
+* As part of the implementation of ``GHC proposal 493 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0493-s…>``_,
+ the ``SpecSig`` constructor of ``Sig`` has been deprecated. It is replaced by
+ the constructor ``SpecSigE`` which supports expressions at the head, rather than
a lone variable.
``ghc-heap`` library
~~~~~~~~~~~~~~~~~~~~
-* The functions `getClosureInfoTbl_maybe`, `getClosureInfoTbl`,
- `getClosurePtrArgs` and `getClosurePtrArgs_maybe` have been added to allow
+* The functions ``getClosureInfoTbl_maybe``, ``getClosureInfoTbl``,
+ ``getClosurePtrArgs`` and ``getClosurePtrArgs_maybe`` have been added to allow
reading of the relevant Closure attributes without reliance on incomplete
selectors.
@@ -225,7 +243,6 @@ Cmm
``ghc-experimental`` versions.
-
``template-haskell`` library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
=====================================
rts/PrimOps.cmm
=====================================
@@ -1210,27 +1210,16 @@ INFO_TABLE_RET(stg_catch_retry_frame, CATCH_RETRY_FRAME,
gcptr trec, outer, arg;
trec = StgTSO_trec(CurrentTSO);
- if (running_alt_code != 1) {
- // When exiting the lhs code of catchRetry# lhs rhs, we need to cleanup
- // the nested transaction.
- // See Note [catchRetry# implementation]
- outer = StgTRecHeader_enclosing_trec(trec);
- (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
- if (r != 0) {
- // Succeeded in first branch
- StgTSO_trec(CurrentTSO) = outer;
- return (ret);
- } else {
- // Did not commit: abort and restart.
- StgTSO_trec(CurrentTSO) = outer;
- jump stg_abort();
- }
- }
- else {
- // nothing to do in the rhs code of catchRetry# lhs rhs, it's already
- // using the parent transaction (not a nested one).
- // See Note [catchRetry# implementation]
- return (ret);
+ outer = StgTRecHeader_enclosing_trec(trec);
+ (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
+ if (r != 0) {
+ // Succeeded (either first branch or second branch)
+ StgTSO_trec(CurrentTSO) = outer;
+ return (ret);
+ } else {
+ // Did not commit: abort and restart.
+ StgTSO_trec(CurrentTSO) = outer;
+ jump stg_abort();
}
}
@@ -1463,26 +1452,21 @@ retry_pop_stack:
outer = StgTRecHeader_enclosing_trec(trec);
if (frame_type == CATCH_RETRY_FRAME) {
- // The retry reaches a CATCH_RETRY_FRAME before the ATOMICALLY_FRAME
-
+ // The retry reaches a CATCH_RETRY_FRAME before the atomic frame
+ ASSERT(outer != NO_TREC);
+ // Abort the transaction attempting the current branch
+ ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
+ ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
if (!StgCatchRetryFrame_running_alt_code(frame) != 0) {
- // Retrying in the lhs of catchRetry# lhs rhs, i.e. in a nested
- // transaction. See Note [catchRetry# implementation]
-
- // check that we have a parent transaction
- ASSERT(outer != NO_TREC);
-
- // Abort the nested transaction
- ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
- ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
-
- // As we are retrying in the lhs code, we must now try the rhs code
- StgTSO_trec(CurrentTSO) = outer;
+ // Retry in the first branch: try the alternative
+ ("ptr" trec) = ccall stmStartTransaction(MyCapability() "ptr", outer "ptr");
+ StgTSO_trec(CurrentTSO) = trec;
StgCatchRetryFrame_running_alt_code(frame) = 1 :: CInt; // true;
R1 = StgCatchRetryFrame_alt_code(frame);
jump stg_ap_v_fast [R1];
} else {
- // Retry in the rhs code: propagate the retry
+ // Retry in the alternative code: propagate the retry
+ StgTSO_trec(CurrentTSO) = outer;
Sp = Sp + SIZEOF_StgCatchRetryFrame;
goto retry_pop_stack;
}
=====================================
rts/RaiseAsync.c
=====================================
@@ -1043,7 +1043,8 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception,
}
case CATCH_STM_FRAME:
- // CATCH_STM frame within an atomically block: abort the
+ case CATCH_RETRY_FRAME:
+ // CATCH frames within an atomically block: abort the
// inner transaction and continue. Eventually we will
// hit the outer transaction that will get frozen (see
// above).
@@ -1055,40 +1056,14 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception,
{
StgTRecHeader *trec = tso -> trec;
StgTRecHeader *outer = trec -> enclosing_trec;
- debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_STM frame");
+ debugTraceCap(DEBUG_stm, cap,
+ "found atomically block delivering async exception");
stmAbortTransaction(cap, trec);
stmFreeAbortedTRec(cap, trec);
tso -> trec = outer;
break;
};
- case CATCH_RETRY_FRAME:
- // CATCH_RETY frame within an atomically block: if we're executing
- // the lhs code, abort the inner transaction and continue; if we're
- // executing thr rhs, continue (no nested transaction to abort. See
- // Note [catchRetry# implementation]). Eventually we will hit the
- // outer transaction that will get frozen (see above).
- //
- // As for the CATCH_STM_FRAME case above, we do not care
- // whether the transaction is valid or not because its
- // possible validity cannot have caused the exception
- // and will not be visible after the abort.
- {
- if (!((StgCatchRetryFrame *)frame) -> running_alt_code) {
- debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (lhs)");
- StgTRecHeader *trec = tso -> trec;
- StgTRecHeader *outer = trec -> enclosing_trec;
- stmAbortTransaction(cap, trec);
- stmFreeAbortedTRec(cap, trec);
- tso -> trec = outer;
- }
- else
- {
- debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (rhs)");
- }
- break;
- };
-
default:
// see Note [Update async masking state on unwind] in Schedule.c
if (*frame == (W_)&stg_unmaskAsyncExceptionszh_ret_info) {
=====================================
rts/STM.c
=====================================
@@ -1505,30 +1505,3 @@ void stmWriteTVar(Capability *cap,
}
/*......................................................................*/
-
-
-
-/*
-
-Note [catchRetry# implementation]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-catchRetry# creates a nested transaction for its lhs:
-- if the lhs transaction succeeds:
- - the lhs transaction is committed
- - its read-variables are merged with those of the parent transaction
- - the rhs code is ignored
-- if the lhs transaction retries:
- - the lhs transaction is aborted
- - its read-variables are merged with those of the parent transaction
- - the rhs code is executed directly in the parent transaction (see #26028).
-
-So note that:
-- lhs code uses a nested transaction
-- rhs code doesn't use a nested transaction
-
-We have to take which case we're in into account (using the running_alt_code
-field of the catchRetry frame) in catchRetry's entry code, in retry#
-implementation, and also when an async exception is received (to cleanup the
-right number of transactions).
-
-*/
=====================================
testsuite/tests/lib/stm/T26028.hs deleted
=====================================
@@ -1,23 +0,0 @@
-module Main where
-
-import GHC.Conc
-
-forever :: IO String
-forever = delay 10 >> forever
-
-terminates :: IO String
-terminates = delay 1 >> pure "terminates"
-
-delay s = threadDelay (1000000 * s)
-
-async :: IO a -> IO (STM a)
-async a = do
- var <- atomically (newTVar Nothing)
- forkIO (a >>= atomically . writeTVar var . Just)
- pure (readTVar var >>= maybe retry pure)
-
-main :: IO ()
-main = do
- x <- mapM async $ terminates : replicate 50000 forever
- r <- atomically (foldr1 orElse x)
- print r
=====================================
testsuite/tests/lib/stm/T26028.stdout deleted
=====================================
@@ -1 +0,0 @@
-"terminates"
=====================================
testsuite/tests/lib/stm/all.T deleted
=====================================
@@ -1 +0,0 @@
-test('T26028', only_ways(['threaded1']), compile_and_run, ['-O2'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7d639a06cdd3b62966257ca3713a8f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7d639a06cdd3b62966257ca3713a8f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/backports-9.14] users-guide/relnotes: More stylistic fixes
by Ben Gamari (@bgamari) 02 Sep '25
by Ben Gamari (@bgamari) 02 Sep '25
02 Sep '25
Ben Gamari pushed to branch wip/backports-9.14 at Glasgow Haskell Compiler / GHC
Commits:
7d639a06 by Ben Gamari at 2025-08-19T18:52:08-04:00
users-guide/relnotes: More stylistic fixes
- - - - -
1 changed file:
- docs/users_guide/9.14.1-notes.rst
Changes:
=====================================
docs/users_guide/9.14.1-notes.rst
=====================================
@@ -52,7 +52,7 @@ Language
That will break the combination of :extension:`OverloadedRecordUpdate` with :extension:`RebindableSyntax`.
-* Multiline strings are now accepted in foreign imports. (#25157)
+* Multiline strings are now accepted in ``foreign import``\ s. (#25157)
* GHC now does a better job at inferring types in calls to ``coerce``: instead of
complaining about ambiguous type variables, GHC will consider that such type
@@ -73,7 +73,7 @@ Language
* The ``-Wdata-kinds-tc`` warning has been deprecated, and the use of promoted
data types in kinds is now an error (rather than a warning) unless the
:extension:`DataKinds` extension is enabled. For example, the following code
- will be rejected unless :extension:`DataKinds` is on:
+ will be rejected unless :extension:`DataKinds` is on: ::
import Data.Kind (Type)
import GHC.TypeNats (Nat)
@@ -143,14 +143,14 @@ Compiler
were accessed using the generated record selector functions, marking the fields
as covered in coverage reports (:ghc-ticket:`17834`).
-- SIMD support in the X86 native code generator has been extended with 128-bit
+- SIMD support in the x86 native code generator has been extended with 128-bit
integer operations. Also, ``shuffleFloatX4#`` and ``shuffleDoubleX2#`` no longer
require ``-mavx``.
GHCi
~~~~
-- :ghci-cmd:`:info` now outputs type declarations with @-binders that are
+- :ghci-cmd:`:info` now outputs type declarations with ``@``-binders that are
considered semantically significant. See the documentation for :ghci-cmd:`:info`
itself for a more detailed explanation.
@@ -176,40 +176,40 @@ Cmm
``ghc`` library
~~~~~~~~~~~~~~~
-* The `UnknownDiagnostic` constructor now takes an additional type argument
+* The ``UnknownDiagnostic`` constructor now takes an additional type argument
for the type of hints corresponding to the diagnostic, and an additional
value-level argument used for existential wrapping of the hints of the inner
diagnostic.
* Changes to the HPT and HUG interface:
- - `addToHpt` and `addListToHPT` were moved from `GHC.Unit.Home.ModInfo` to `GHC.Unit.Home.PackageTable` and deprecated in favour of `addHomeModInfoToHpt` and `addHomeModInfosToHpt`.
- - `UnitEnvGraph` and operations `unitEnv_lookup_maybe`, `unitEnv_foldWithKey, `unitEnv_singleton`, `unitEnv_adjust`, `unitEnv_insert`, `unitEnv_new` were moved from `GHC.Unit.Env` to `GHC.Unit.Home.Graph`.
- - The HomePackageTable (HPT) is now exported from `GHC.Unit.Home.PackageTable`,
+ - ``addToHpt`` and ``addListToHPT`` were moved from ``GHC.Unit.Home.ModInfo`` to ``GHC.Unit.Home.PackageTable`` and deprecated in favour of ``addHomeModInfoToHpt`` and ``addHomeModInfosToHpt``.
+ - ``UnitEnvGraph`` and operations ``unitEnv_lookup_maybe``, ``unitEnv_foldWithKey, ``unitEnv_singleton``, ``unitEnv_adjust``, ``unitEnv_insert``, ``unitEnv_new`` were moved from ``GHC.Unit.Env`` to ``GHC.Unit.Home.Graph``.
+ - The HomePackageTable (HPT) is now exported from ``GHC.Unit.Home.PackageTable``,
and is now backed by an IORef to avoid by construction very bad memory leaks.
This means the API to the HPT now is for the most part in IO. For instance,
- `emptyHomePackageTable` and `addHomeModInfoToHpt` are now in IO.
- - `mkHomeUnitEnv` was moved to `GHC.Unit.Home.PackageTable`, and now takes two
- extra explicit arguments. To restore previous behaviour, pass `emptyUnitState`
- and `Nothing` as the first two arguments additionally.
- - `hugElts` was removed. Users should prefer `allUnits` to get the keys of the
- HUG (the typical use case), or `traverse` or `unitEnv_foldWithKey` in other
+ ``emptyHomePackageTable`` and ``addHomeModInfoToHpt`` are now in IO.
+ - ``mkHomeUnitEnv`` was moved to ``GHC.Unit.Home.PackageTable``, and now takes two
+ extra explicit arguments. To restore previous behaviour, pass ``emptyUnitState``
+ and ``Nothing`` as the first two arguments additionally.
+ - ``hugElts`` was removed. Users should prefer ``allUnits`` to get the keys of the
+ HUG (the typical use case), or ``traverse`` or ``unitEnv_foldWithKey`` in other
cases.
-* Changes to `Language.Haskell.Syntax.Expr`
+* Changes to ``Language.Haskell.Syntax.Expr``
- - The `ParStmtBlock` list argument of the `ParStmt` constructor of `StmtLR` is now `NonEmpty`.
+ - The ``ParStmtBlock`` list argument of the ``ParStmt`` constructor of ``StmtLR`` is now ``NonEmpty``.
-* As part of the implementation of `GHC proposal 493 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0493-s…>`_,
- the `SpecSig` constructor of `Sig` has been deprecated. It is replaced by
- the constructor `SpecSigE` which supports expressions at the head, rather than
+* As part of the implementation of ``GHC proposal 493 <https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0493-s…>``_,
+ the ``SpecSig`` constructor of ``Sig`` has been deprecated. It is replaced by
+ the constructor ``SpecSigE`` which supports expressions at the head, rather than
a lone variable.
``ghc-heap`` library
~~~~~~~~~~~~~~~~~~~~
-* The functions `getClosureInfoTbl_maybe`, `getClosureInfoTbl`,
- `getClosurePtrArgs` and `getClosurePtrArgs_maybe` have been added to allow
+* The functions ``getClosureInfoTbl_maybe``, ``getClosureInfoTbl``,
+ ``getClosurePtrArgs`` and ``getClosurePtrArgs_maybe`` have been added to allow
reading of the relevant Closure attributes without reliance on incomplete
selectors.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7d639a06cdd3b62966257ca3713a8f1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7d639a06cdd3b62966257ca3713a8f1…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Zubin pushed to branch wip/26264 at Glasgow Haskell Compiler / GHC
Commits:
34fc50c1 by Ben Gamari at 2025-08-11T13:36:25-04:00
Kill IOPort#
This type is unnecessary, having been superceded by `MVar` and a rework
of WinIO's blocking logic.
See #20947.
See https://github.com/haskell/core-libraries-committee/issues/213.
- - - - -
56b32c5a by sheaf at 2025-08-12T10:00:19-04:00
Improve deep subsumption
This commit improves the DeepSubsumption sub-typing implementation
in GHC.Tc.Utils.Unify.tc_sub_type_deep by being less eager to fall back
to unification.
For example, we now are properly able to prove the subtyping relationship
((∀ a. a->a) -> Int) -> Bool <= β[tau] Bool
for an unfilled metavariable β. In this case (with an AppTy on the right),
we used to fall back to unification. No longer: now, given that the LHS
is a FunTy and that the RHS is a deep rho type (does not need any instantiation),
we try to make the RHS into a FunTy, viz.
β := (->) γ
We can then continue using covariance & contravariance of the function
arrow, which allows us to prove the subtyping relationship, instead of
trying to unify which would cause us to error out with:
Couldn't match expected type ‘β’ with actual type ‘(->) ((∀ a. a -> a) -> Int)
See Note [FunTy vs non-FunTy case in tc_sub_type_deep] in GHC.Tc.Utils.Unify.
The other main improvement in this patch concerns type inference.
The main subsumption logic happens (before & after this patch) in
GHC.Tc.Gen.App.checkResultTy. However, before this patch, all of the
DeepSubsumption logic only kicked in in 'check' mode, not in 'infer' mode.
This patch adds deep instantiation in the 'infer' mode of checkResultTy
when we are doing deep subsumption, which allows us to accept programs
such as:
f :: Int -> (forall a. a->a)
g :: Int -> Bool -> Bool
test1 b =
case b of
True -> f
False -> g
test2 b =
case b of
True -> g
False -> f
See Note [Deeply instantiate in checkResultTy when inferring].
Finally, we add representation-polymorphism checks to ensure that the
lambda abstractions we introduce when doing subsumption obey the
representation polymorphism invariants of Note [Representation polymorphism invariants]
in GHC.Core. See Note [FunTy vs FunTy case in tc_sub_type_deep].
This is accompanied by a courtesy change to `(<.>) :: HsWrapper -> HsWrapper -> HsWrapper`,
adding the equation:
WpCast c1 <.> WpCast c2 = WpCast (c1 `mkTransCo` c2)
This is useful because mkWpFun does not introduce an eta-expansion when
both of the argument & result wrappers are casts; so this change allows
us to avoid introducing lambda abstractions when casts suffice.
Fixes #26225
- - - - -
d175aff8 by Sylvain Henry at 2025-08-12T10:01:31-04:00
Add regression test for #18619
- - - - -
a3983a26 by Sylvain Henry at 2025-08-12T10:02:20-04:00
RTS: remove some TSAN annotations (#20464)
Use RELAXED_LOAD_ALWAYS macro instead.
- - - - -
0434af81 by Ben Gamari at 2025-08-12T10:03:02-04:00
Bump time submodule to 1.15
Also required bumps of Cabal, directory, and hpc.
- - - - -
62899117 by Florian Ragwitz at 2025-08-13T21:01:34-04:00
Extend record-selector usage ticking to all binds using a record field
This extends the previous handling of ticking for RecordWildCards and
NamedFieldPuns to all var bindings that involve record selectors.
Note that certain patterns such as `Foo{foo = 42}` will currently not tick the
`foo` selector, as ticking is triggered by `HsVar`s.
Closes #26191.
- - - - -
b37b3af7 by Florian Ragwitz at 2025-08-13T21:01:34-04:00
Add release notes for 9.16.1 and move description of latest HPC changes there.
- - - - -
a5e4b7d9 by Ben Gamari at 2025-08-13T21:02:18-04:00
rts: Clarify rationale for undefined atomic wrappers
Since c06e3f46d24ef69f3a3d794f5f604cb8c2a40cbc the RTS has declared
various atomic operation wrappers defined by ghc-internal as undefined.
While the rationale for this isn't clear from the commit message, I
believe that this is necessary due to the unregisterised backend.
Specifically, the code generator will reference these symbols when
compiling RTS Cmm sources.
- - - - -
50842f83 by Andreas Klebinger at 2025-08-13T21:03:01-04:00
Make unexpected LLVM versions a warning rather than an error.
Typically a newer LLVM version *will* work so erroring out if
a user uses a newer LLVM version is too aggressive.
Fixes #25915
- - - - -
c91e2650 by fendor at 2025-08-13T21:03:43-04:00
Store `StackTrace` and `StackSnapshot` in `Backtraces`
Instead of decoding the stack traces when collecting the `Backtraces`,
defer this decoding until actually showing the `Backtraces`.
This allows users to customise how `Backtraces` are displayed by
using a custom implementation of `displayExceptionWithInfo`, overwriting
the default implementation for `Backtraces` (`displayBacktraces`).
- - - - -
dee28cdd by fendor at 2025-08-13T21:03:43-04:00
Allow users to customise the collection of exception annotations
Add a global `CollectExceptionAnnotationMechanism` which determines how
`ExceptionAnnotation`s are collected upon throwing an `Exception`.
This API is exposed via `ghc-experimental`.
By overriding how we collect `Backtraces`, we can control how the
`Backtraces` are displayed to the user by newtyping `Backtraces` and
giving a different instance for `ExceptionAnnotation`.
A concrete use-case for this feature is allowing us to experiment with
alternative stack decoders, without having to modify `base`, which take
additional information from the stack frames.
This commit does not modify how `Backtraces` are currently
collected or displayed.
- - - - -
66024722 by fendor at 2025-08-13T21:03:43-04:00
Expose Backtraces internals from ghc-experimental
Additionally, expose the same API `base:Control.Exception.Backtrace`
to make it easier to use as a drop-in replacement.
- - - - -
a766286f by Reed Mullanix at 2025-08-13T21:04:36-04:00
ghc-internal: Fix naturalAndNot for NB/NS case
When the first argument to `naturalAndNot` is larger than a `Word` and the second is `Word`-sized, `naturalAndNot` will truncate the
result:
```
>>> naturalAndNot ((2 ^ 65) .|. (2 ^ 3)) (2 ^ 3)
0
```
In contrast, `naturalAndNot` does not truncate when both arguments are larger than a `Word`, so this appears to be a bug.
Luckily, the fix is pretty easy: we just need to call `bigNatAndNotWord#` instead of truncating.
Fixes #26230
- - - - -
3506fa7d by Simon Hengel at 2025-08-13T21:05:18-04:00
Report -pgms as a deprecated flag
(instead of reporting an unspecific warning)
Before:
on the commandline: warning:
Object splitting was removed in GHC 8.8
After:
on the commandline: warning: [GHC-53692] [-Wdeprecated-flags]
-pgms is deprecated: Object splitting was removed in GHC 8.8
- - - - -
51c701fe by Zubin Duggal at 2025-08-13T21:06:00-04:00
testsuite: Be more permissive when filtering out GNU_PROPERTY_TYPE linker warnings
The warning text is slightly different with ld.bfd.
Fixes #26249
- - - - -
dfe6f464 by Simon Hengel at 2025-08-13T21:06:43-04:00
Refactoring: Don't misuse `MCDiagnostic` for lint messages
`MCDiagnostic` is meant to be used for compiler diagnostics.
Any code that creates `MCDiagnostic` directly, without going through
`GHC.Driver.Errors.printMessage`, side steps `-fdiagnostics-as-json`
(see e.g. !14475, !14492 !14548).
To avoid this in the future I want to control more narrowly who creates
`MCDiagnostic` (see #24113).
Some parts of the compiler use `MCDiagnostic` purely for formatting
purposes, without creating any real compiler diagnostics. This change
introduces a helper function, `formatDiagnostic`, that can be used in
such cases instead of constructing `MCDiagnostic`.
- - - - -
a8b2fbae by Teo Camarasu at 2025-08-13T21:07:24-04:00
rts: ensure MessageBlackHole.link is always a valid closure
We turn a MessageBlackHole into an StgInd in wakeBlockingQueue().
Therefore it's important that the link field, which becomes the
indirection field, always points to a valid closure.
It's unclear whether it's currently possible for the previous behaviour
to lead to a crash, but it's good to be consistent about this invariant nonetheless.
Co-authored-by: Andreas Klebinger <klebinger.andreas(a)gmx.at>
- - - - -
4021181e by Teo Camarasu at 2025-08-13T21:07:24-04:00
rts: spin if we see a WHITEHOLE in messageBlackHole
When a BLACKHOLE gets cancelled in raiseAsync, we indirect to a THUNK.
GC can then shortcut this, replacing our BLACKHOLE with a fresh THUNK.
This THUNK is not guaranteed to have a valid indirectee field.
If at the same time, a message intended for the previous BLACKHOLE is
processed and concurrently we BLACKHOLE the THUNK, thus temporarily
turning it into a WHITEHOLE, we can get a segfault, since we look at the
undefined indirectee field of the THUNK
The fix is simple: spin if we see a WHITEHOLE, and it will soon be
replaced with a valid BLACKHOLE.
Resolves #26205
- - - - -
1107af89 by Oleg Grenrus at 2025-08-13T21:08:06-04:00
Allow defining HasField instances for naughty fields
Resolves #26295
... as HasField solver doesn't solve for fields with "naughty"
selectors, we could as well allow defining HasField instances for these
fields.
- - - - -
020e7587 by Sylvain Henry at 2025-08-13T21:09:00-04:00
Fix Data.List unqualified import warning
- - - - -
fd811ded by Simon Peyton Jones at 2025-08-14T17:56:47-04:00
Make injecting implicit bindings into its own pass
Previously we were injecting "impliicit bindings" (data constructor
worker and wrappers etc)
- both at the end of CoreTidy,
- and at the start of CorePrep
This is unpleasant and confusing. This patch puts it it its own pass,
addImplicitBinds, which runs between the two.
The function `GHC.CoreToStg.AddImplicitBinds.addImplicitBinds` now takes /all/
TyCons, not just the ones for algebraic data types. That change ripples
through to
- corePrepPgm
- doCodeGen
- byteCodeGen
All take [TyCon] which includes all TyCons
- - - - -
9bd7fcc5 by Simon Peyton Jones at 2025-08-14T17:56:47-04:00
Implement unary classes
The big change is described exhaustively in
Note [Unary class magic] in GHC.Core.TyCon
Other changes
* We never unbox class dictionaries in worker/wrapper. This has been true for some
time now, but the logic is now centralised in functions in
GHC.Core.Opt.WorkWrap.Utils, namely `canUnboxTyCon`, and `canUnboxArg`
See Note [Do not unbox class dictionaries] in GHC.Core.Opt.WorkWrap.Utils.
* Refactored the `notWorthFloating` logic in GHc.Core.Opt.SetLevels.
I can't remember if I actually changed any behaviour here, but if so it's
only in a corner cases.
* Fixed a bug in `GHC.Core.TyCon.isEnumerationTyCon`, which was wrongly returning
True for (##).
* Remove redundant Role argument to `liftCoSubstWithEx`. It was always
Representational.
* I refactored evidence generation in the constraint solver:
* Made GHC.Tc.Types.Evidence contain better abstactions for evidence
generation.
* I deleted the file `GHC.Tc.Types.EvTerm` and merged its (small) contents
elsewhere. It wasn't paying its way.
* Made evidence for implicit parameters go via a proper abstraction.
* Fix inlineBoringOk; see (IB6) in Note [inlineBoringOk]
This fixes a slowdown in `countdownEffectfulDynLocal`
in the `effectful` library.
Smaller things
* Rename `isDataTyCon` to `isBoxedDataTyCon`.
* GHC.Core.Corecion.liftCoSubstWithEx was only called with Representational role,
so I baked that into the function and removed the argument.
* Get rid of `GHC.Core.TyCon.tyConSingleAlgDataCon_maybe` in favour of calling
`not isNewTyCon` at the call sites; more explicit.
* Refatored `GHC.Core.TyCon.isInjectiveTyCon`; but I don't think I changed its
behaviour
* Moved `decomposeIPPred` to GHC.Core.Predicate
Compile time performance changes:
geo. mean +0.1%
minimum -6.8%
maximum +14.4%
The +14% one is in T21839c, where it seems that a bit more inlining
is taking place. That seems acceptable; and the average change is small
Metric Decrease:
LargeRecord
T12227
T12707
T16577
T21839r
T5642
Metric Increase:
T15164
T21839c
T3294
T5321FD
T5321Fun
WWRec
- - - - -
b4075d71 by Simon Peyton Jones at 2025-08-14T17:56:47-04:00
Slight improvement to pre/postInlineUnconditionally
Avoids an extra simplifier iteration
- - - - -
9e443596 by Simon Peyton Jones at 2025-08-14T17:56:47-04:00
Fix a long-standing assertion error in normSplitTyConApp_maybe
- - - - -
91310ad0 by Simon Peyton Jones at 2025-08-14T17:56:47-04:00
Add comment to coercion optimiser
- - - - -
5b841d82 by Teo Camarasu at 2025-08-14T17:57:56-04:00
template-haskell: move some identifiers from ghc-internal to template-haskell
These identifiers are not used internally by the compiler. Therefore we
have no reason for them to be in ghc-internal.
By moving them to template-haskell, we benefit from it being easier to
change them and we avoid having to build them in stage0.
Resolves #26048
- - - - -
33e2c7e5 by Teo Camarasu at 2025-08-14T17:57:56-04:00
template-haskell: transfer $infix note to public module
This Haddock note should be in the public facing module
- - - - -
2a411fc4 by Sylvain Henry at 2025-08-14T17:59:09-04:00
JS: export HEAP8 symbol (#26290)
Newer Emscripten requires this.
- - - - -
248f78ca by Ben Gamari at 2025-08-14T17:59:51-04:00
users-guide: Drop the THREAD_RUNNABLE event
As of f361281c89fbce42865d8b8b27b0957205366186 it is no longer emitted.
- - - - -
706d33e3 by Recursion Ninja at 2025-08-15T04:12:12-04:00
Resolving issues #20645 and #26109
Correctly sign extending and casting smaller bit width types for LLVM operations:
- bitReverse8#
- bitReverse16#
- bitReverse32#
- byteSwap16#
- byteSwap32#
- pdep8#
- pdep16#
- pext8#
- pext16#
- - - - -
1cdc6f46 by Cheng Shao at 2025-08-15T04:12:56-04:00
hadrian: enforce have_llvm=False for wasm32/js
This patch fixes hadrian to always pass have_llvm=False to the
testsuite driver for wasm32/js targets. These targets don't really
support the LLVM backend, and the optllvm test way doesn't work. We
used to special-case wasm32/js to avoid auto-adding optllvm way in
testsuite/config/ghc, but this is still problematic if someone writes
a new LLVM-related test and uses something like when(have_llvm(),
extra_ways(["optllvm"])). So better just enforce have_llvm=False for
these targets here.
- - - - -
ca03226d by Ben Gamari at 2025-08-18T13:43:20+00:00
configure: Allow use of LLVM 20
- - - - -
783cd7d6 by Cheng Shao at 2025-08-18T20:13:14-04:00
compiler: use `UniqMap` instead of `Map` for `BCEnv` in bytecode compiler
The bytecode compiler maintains a `BCEnv` which was previously `Map Id
StackDepth`. Given `Id` is `Uniquable`, we might as well use `UniqMap`
here as a more efficient data structure, hence this patch.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
58e46da9 by fendor at 2025-08-18T20:13:56-04:00
rts: Strip lower three bits when hashing Word instead of lower eight bits
- - - - -
45dbfa23 by Cheng Shao at 2025-08-18T20:14:37-04:00
libffi: update to 3.5.2
Bumps libffi submodule.
- - - - -
54be78ef by Ben Gamari at 2025-08-19T16:28:05-04:00
testsuite: Fix T20006b
This test is supposed to fail for non-threaded ways yet it
was previously marked as only failing in `normal`.
Fix this.
- - - - -
f4bac607 by Simon Peyton Jones at 2025-08-19T16:28:47-04:00
Take yet more care with reporting redundant constraints
This small patch fixes #25992, which relates to reporting redundant
constraints on default-method declarations.
See (TRC5) in Note [Tracking redundant constraints]
- - - - -
ab130fec by fendor at 2025-08-19T16:29:29-04:00
Bump dependencies of hadrian-bootstrap-gen to use GHC 9.6.7
- - - - -
6d02ac6f by fendor at 2025-08-19T16:29:29-04:00
Bump required GHC version for test-bootstrap jobs to 9.10.1
Include test-bootstrap job for GHC 9.12.2.
Update hadrian bootstrap plans use GHC 9.10 and 9.12
Remove older GHC bootstrap configurations.
We require at least GHC 9.10.1 to build GHC.
Adds plans for:
* 9.10.1
* 9.10.2
* 9.12.1
* 9.12.2
- - - - -
9e857171 by Brandon Chinn at 2025-08-20T11:47:46-04:00
Don't warn unused-imports with used generated imports
Fixes #21730
* The old notion of "implicit" import has been renamed to "generated". See Note [Generated imports] in GHC.Hs.ImpExp.
* ImportMap now keeps track of generated and user-written imports separately. This avoids the fake SrcSpan we used to give the implicit Prelude import, and the hack that went with it.
* -ddump-minimal-imports now considers generated imports (but still only
warns on + prints user-written imports)
* bestImport considers generated imports to take priority over user-written imports.
- - - - -
9fb3bad4 by Ben Gamari at 2025-08-20T11:48:31-04:00
mailmap: Use ben(a)well-typed.com more liberally
Nearly all of this work was done while working for Well-Typed.
- - - - -
774fec37 by Ben Gamari at 2025-08-20T11:49:15-04:00
Add primop to annotate the call stack with arbitrary data
We introduce a new primop `annotateStack#` which allows us to push
arbitrary data onto the call-stack.
This allows us to extract the data later when decoding the stack, for
example when an exception is thrown, showing more information to the
user without having to annotate the full call-stack with `HasCallStack`
constraints.
A new stack frame value is introduced `AnnFrame`, which consists of
nothing but a generic payload.
The primop has a small wrapper API that allows users to annotate their
call-stack in programs.
There is a pure API and an IO-based one. The former is a little bit
dubious, as it affects the evaluation of a program, so use with care.
The latter is "safe", as it doesn't change the evaluation of the
program.
The stack annotation mechanism is similarly implemented to the
`ExceptionAnnotation` and `Exception`, there is a typeclass to indicate
something can be pushed onto the call-stack and all values are wrapped
in the existential `SomeStackAnnotation`, which recover the type of the
annotation payload.
There is currently no builtin way to show the stack annotations when
`Backtraces` are displayed (i.e., when showing stack traces to the user),
which we will address in a follow-up MR.
-------------------------
Metric Increase:
ghc_experimental_so
-------------------------
We increase the size of the package, so this is not unreasonable.
Co-Authored-By: fendor <fendor(a)posteo.de>
Co-Authored-By: Ben Gamari <bgamari.foss(a)gmail.com>
- - - - -
fdfa3892 by Ben Gamari at 2025-08-20T11:49:57-04:00
testsuite: Add regression test for #24606
- - - - -
39b2e382 by Cheng Shao at 2025-08-20T11:50:40-04:00
compiler: only use `Name` instead of `Id` in `SptEntry`
As a part of #26298, this patch refactors `SptEntry` to only carry a
`Name` instead of `Id`: we do not care about extra information like
caffyness or type at all in any static pointer related codegen logic.
This is necessary to make `SptEntry` serializable, as a part of the
grand plan of serializable bytecode.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
276f8ea8 by Vekhir -- at 2025-08-20T11:51:35-04:00
Bump Cabal dependency
- - - - -
0b9c7437 by Zubin Duggal at 2025-08-20T11:52:18-04:00
ci: Teach ci.sh to fetch FreeBSD artifacts from ghcup unofficial bindists and bootstrap compiler on FreeBSD to 9.10.1
Also refactor fetch_ghc logic in ci.sh, renaming the GHC_VERSION enviorment configuration variable to FETCH_GHC_VERSION,
making it clear that it is intended for use on platforms like Windows and FreeBSD where we don't want to use the GHC
excecutable from the platform environment and instead need to download and install GHC-$FETCH_GHC_VERSION from a release
bindist.
Fixes #26296
- - - - -
b2914797 by Cheng Shao at 2025-08-20T11:53:00-04:00
driver: use UniqSet for hiddenModules in DynFlags/FinderOpts
This patch replaces Set ModuleName with UniqSet ModuleName in
DynFlags.hiddenModules and FinderOpts.finder_hiddenModules for
improved efficiency.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
0335d899 by Cheng Shao at 2025-08-20T11:53:00-04:00
driver: use UniqMap ModuleName in the finder
This patch replaces Map ModuleName with UniqMap ModuleName in the
finder for improved efficiency.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
91f4faaa by Cheng Shao at 2025-08-20T11:53:43-04:00
configure: check python3 version and require minimal 3.7
Since !9515, the testsuite driver requires python3 version to be at
least 3.7, though this has never been checked by configure logic. This
patch implements the version check. Fixes #23234.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
df4ee9b4 by Cheng Shao at 2025-08-20T11:54:25-04:00
compiler: use zero cost coerce in GHC.CmmToAsm.CFG.loopInfo
This patch refactors GHC.CmmToAsm.CFG.loopInfo to use zero cost coerce
and thus addresses the TODO. For coerce to work, constructors of
Label/LabelMap/LabelSet from GHC.Cmm.Dataflow.Label are exposed,
though I believe it's a worthy tradeoff to avoid unnecessary runtime
cost without using unsafeCoerce, since the latter could be a landmine
for future refactoring.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
ccda188d by Simon Peyton Jones at 2025-08-20T11:55:07-04:00
Start with empty inerts in shortcut solving
When short-cut solving we were starting with an inert set that had
unsolved Wanteds. This caused an infinite loop (#26314), because a
typechecker plugin kept being given that unsolved Wanted.
It's better just to start with an empty inert set
- - - - -
c8882ed7 by Ben Gamari at 2025-08-20T11:55:49-04:00
configure: Bump minimal bootstrap GHC version to 9.8
- - - - -
f0a19d74 by fendor at 2025-08-20T19:55:00-04:00
Remove deprecated functions from the ghci package
- - - - -
ebeb991b by fendor at 2025-08-20T19:55:00-04:00
base: Remove unstable heap representation details from GHC.Exts
- - - - -
e368e247 by Rodrigo Mesquita at 2025-08-20T19:55:42-04:00
bytecode: Use 32bits for breakpoint index
Fixes #26325
- - - - -
42724462 by Simon Hengel at 2025-08-21T17:52:11-04:00
Serialize wired-in names as external names when creating HIE files
Note that the domain of de-serialized names stays the same.
Specifically, for known-key names, before `lookupKnownKeyName` was used,
while now this is handled by `lookupOrigNameCache` which captures the
same range provided that the OrigNameCache has been initialized with
`knownKeyNames` (which is the case by default).
(fixes #26238)
- - - - -
6a43f8ec by Cheng Shao at 2025-08-21T17:52:52-04:00
compiler: fix closure C type in SPT init code
This patch fixes the closure C type in SPT init code to StgClosure,
instead of the previously incorrect StgPtr. Having an incorrect C type
makes SPT init code not compatible with other foreign stub generation
logic, which may also emit their own extern declarations for the same
closure symbols and thus will clash with the incorrect prototypes in
SPT init code.
- - - - -
5b5d9d47 by Ben Gamari at 2025-08-25T14:29:35-04:00
Revert "STM: don't create a transaction in the rhs of catchRetry# (#26028)"
This reverts commit 0a5836891ca29836a24c306d2a364c2e4b5377fd
- - - - -
10f06163 by Cheng Shao at 2025-08-25T14:30:16-04:00
wasm: ensure setKeepCAFs() is called in ghci
This patch is a critical bugfix for #26106, see comment and linked
issue for details.
- - - - -
bedc1004 by Cheng Shao at 2025-08-26T09:31:18-04:00
compiler: use zero cost coerce in hoopl setElems/mapToList
This patch is a follow-up of !14680 and changes setElems/mapToList in
GHC/Cmm/Dataflow/Label to use coerce instead of mapping mkHooplLabel
over the keys.
- - - - -
13250d97 by Ryan Scott at 2025-08-26T09:31:59-04:00
Reject infix promoted data constructors without DataKinds
In the rename, make sure to apply the same `DataKinds` checks for both
`HsTyVar` (for prefix promoted data constructors) and `HsOpTy` (for infix
promoted data constructors) alike.
Fixes #26318.
- - - - -
37655c46 by Teo Camarasu at 2025-08-26T15:24:51-04:00
tests: disable T22859 under LLVM
This test was failing under the LLVM backend since the allocations
differ from the NCG.
Resolves #26282
- - - - -
2cbba9d6 by Teo Camarasu at 2025-08-26T15:25:33-04:00
base-exports: update version numbers
As the version of the compiler has been bumped, a lot of the embedded
version numbers will need to be updated if we ever run this test with
`--test-accept` so let's just update them now, and keep future diffs
clean.
- - - - -
f9f2ffcf by Alexandre Esteves at 2025-08-27T07:19:14-04:00
Import new name for 'utimbuf' on windows to fix #26337
Fixes an `-Wincompatible-pointer-types` instance that turns into an error on
recent toolchains and surfaced as such on nixpkgs when doing linux->ucrt cross.
This long-standing warning has been present at least since 9.4:
```
C:\GitLabRunner\builds\0\1709189\tmp\ghc16652_0\ghc_4.c:26:115: error:
warning: incompatible pointer types passing 'struct utimbuf *' to parameter of type 'struct _utimbuf *' [-Wincompatible-pointer-types]
|
26 | HsInt32 ghczuwrapperZC9ZCbaseZCSystemziPosixziInternalsZCzuutime(char* a1, struct utimbuf* a2) {return _utime(a1, a2);}
| ^
HsInt32 ghczuwrapperZC9ZCbaseZCSystemziPosixziInternalsZCzuutime(char* a1, struct utimbuf* a2) {return _utime(a1, a2);}
^~
C:\GitLabRunner\builds\0\1709189\_build\stage0\lib\..\..\mingw\x86_64-w64-mingw32\include\sys\utime.h:109:72: error:
note: passing argument to parameter '_Utimbuf' here
|
109 | __CRT_INLINE int __cdecl _utime(const char *_Filename,struct _utimbuf *_Utimbuf) {
| ^
__CRT_INLINE int __cdecl _utime(const char *_Filename,struct _utimbuf *_Utimbuf) {
```
- - - - -
ae89f000 by Hassan Al-Awwadi at 2025-08-27T07:19:56-04:00
Adds the fucnction addDependentDirectory to Q, resolving issue #26148.
This function adds a new directory to the list of things a module depends upon. That means that when the contents of the directory change, the recompilation checker will notice this and the module will be recompiled. Documentation has also been added for addDependentFunction and addDependentDirectory in the user guide.
- - - - -
00478944 by Simon Peyton Jones at 2025-08-27T16:48:30+01:00
Comments only
- - - - -
a7884589 by Simon Peyton Jones at 2025-08-28T11:08:23+01:00
Type-family occurs check in unification
The occurs check in `GHC.Core.Unify.uVarOrFam` was inadequate in dealing
with type families.
Better now. See Note [The occurs check in the Core unifier].
As I did this I realised that the whole apartness thing is trickier than I
thought: see the new Note [Shortcomings of the apartness test]
- - - - -
8adfc222 by sheaf at 2025-08-28T19:47:17-04:00
Fix orientation in HsWrapper composition (<.>)
This commit fixes the order in which WpCast HsWrappers are composed,
fixing a bug introduced in commit 56b32c5a2d5d7cad89a12f4d74dc940e086069d1.
Fixes #26350
- - - - -
eb2ab1e2 by Oleg Grenrus at 2025-08-29T11:00:53-04:00
Generalise thNameToGhcName by adding HasHscEnv
There were multiple single monad-specific `getHscEnv` across codebase.
HasHscEnv is modelled on HasDynFlags.
My first idea was to simply add thNameToGhcNameHsc and
thNameToGhcNameTc, but those would been exactly the same
as thNameToGhcName already.
Also add an usage example to thNameToGhcName and mention that it's
recommended way of looking up names in GHC plugins
- - - - -
2d575a7f by fendor at 2025-08-29T11:01:36-04:00
configure: Bump minimal bootstrap GHC version to 9.10
- - - - -
716274a5 by Simon Peyton Jones at 2025-08-29T17:27:12-04:00
Fix deep subsumption again
This commit fixed #26255:
commit 56b32c5a2d5d7cad89a12f4d74dc940e086069d1
Author: sheaf <sam.derbyshire(a)gmail.com>
Date: Mon Aug 11 15:50:47 2025 +0200
Improve deep subsumption
This commit improves the DeepSubsumption sub-typing implementation
in GHC.Tc.Utils.Unify.tc_sub_type_deep by being less eager to fall back
to unification.
But alas it still wasn't quite right for view patterns: #26331
This MR does a generalisation to fix it. A bit of a sledgehammer to crack
a nut, but nice.
* Add a field `ir_inst :: InferInstFlag` to `InferResult`, where
```
data InferInstFlag = IIF_Sigma | IIF_ShallowRho | IIF_DeepRho
```
* The flag says exactly how much `fillInferResult` should instantiate
before filling the hole.
* We can also use this to replace the previous very ad-hoc `tcInferSigma`
that was used to implement GHCi's `:type` command.
- - - - -
27206c5e by sheaf at 2025-08-29T17:28:14-04:00
Back-compat for TH SpecialiseP data-con of Pragma
This commit improves the backwards-compatibility story for the
SpecialiseP constructor of the Template Haskell 'Pragma' datatype.
Instead of keeping the constructor but deprecating it, this commit makes
it into a bundled pattern synonym of the Pragma datatype. We no longer
deprecate it; it's useful for handling old-form specialise pragmas.
- - - - -
26dbcf61 by fendor at 2025-08-30T05:10:08-04:00
Move stack decoding logic from ghc-heap to ghc-internal
The stack decoding logic in `ghc-heap` is more sophisticated than the one
currently employed in `CloneStack`. We want to use the stack decoding
implementation from `ghc-heap` in `base`.
We cannot simply depend on `ghc-heap` in `base` due do bootstrapping
issues.
Thus, we move the code that is necessary to implement stack decoding to
`ghc-internal`. This is the right location, as we don't want to add a
new API to `base`.
Moving the stack decoding logic and re-exposing it in ghc-heap is
insufficient, though, as we have a dependency cycle between.
* ghc-heap depends on stage1:ghc-internal
* stage0:ghc depends on stage0:ghc-heap
To fix this, we remove ghc-heap from the set of `stage0` dependencies.
This is not entirely straight-forward, as a couple of boot dependencies,
such as `ghci` depend on `ghc-heap`.
Luckily, the boot compiler of GHC is now >=9.10, so we can migrate `ghci`
to use `ghc-internal` instead of `ghc-heap`, which already exports the
relevant modules.
However, we cannot 100% remove ghc's dependency on `ghc-heap`, since
when we compile `stage0:ghc`, `stage1:ghc-internal` is not yet
available.
Thus, when we compile with the boot-compiler, we still depend on an
older version of `ghc-heap`, and only use the modules from `ghc-internal`,
if the `ghc-internal` version is recent enough.
-------------------------
Metric Increase:
T24602_perf_size
T25046_perf_size_gzip
T25046_perf_size_unicode
T25046_perf_size_unicode_gzip
size_hello_artifact
size_hello_artifact_gzip
size_hello_unicode
size_hello_unicode_gzip
-------------------------
These metric increases are unfortunate, they are most likely caused by
the larger (literally in terms of lines of code) stack decoder implementation
that are now linked into hello-word binaries.
On linux, it is almost a 10% increase, which is considerable.
- - - - -
bd80bb70 by fendor at 2025-08-30T05:10:08-04:00
Implement `decode` in terms of `decodeStackWithIpe`
Uses the more efficient stack decoder implementation.
- - - - -
24441165 by fendor at 2025-08-30T05:10:08-04:00
Remove stg_decodeStackzh
- - - - -
fb9cc882 by Simon Peyton Jones at 2025-08-30T05:10:51-04:00
Fix a long standing bug in the coercion optimiser
We were mis-optimising ForAllCo, leading to #26345
Part of the poblem was the tricky tower of abstractions leading to
the dreadful
GHC.Core.TyCo.Subst.substForAllCoTyVarBndrUsing
This function was serving two masters: regular substitution, but also
coercion optimsation. So tricky was it that it did so wrong.
In this MR I locate all the fancy footwork for coercion optimisation
in GHC.Core.Coercion.Opt, where it belongs. That leaves substitution
free to be much simpler.
- - - - -
6c78de2d by Sylvain Henry at 2025-09-01T08:46:19-04:00
Driver: substitute virtual Prim module in --make mode too
When we build ghc-internal with --make (e.g. with cabal-install), we
need to be careful to substitute the virtual interface file for
GHC.Internal.Prim:
- after code generation (we generate code for an empty module, so we get
an empty interface)
- when we try to reload its .hi file
- - - - -
26e0db16 by fendor at 2025-09-01T08:47:01-04:00
Expose Stack Annotation frames in IPE backtraces by default
When decoding the Haskell-native call stack and displaying the IPE information
for the stack frames, we print the `StackAnnotation` of the `AnnFrame` by default.
This means, when an exception is thrown, any intermediate stack annotations will
be displayed in the `IPE Backtrace`.
Example backtrace:
```
Exception: ghc-internal:GHC.Internal.Exception.ErrorCall:
Oh no!
IPE backtrace:
annotateCallStackIO, called at app/Main.hs:48:10 in backtrace-0.1.0.0-inplace-server:Main
annotateCallStackIO, called at app/Main.hs:46:13 in backtrace-0.1.0.0-inplace-server:Main
Main.handler (app/Main.hs:(46,1)-(49,30))
Main.liftIO (src/Servant/Server/Internal/Handler.hs:30:36-42)
Servant.Server.Internal.Delayed.runHandler' (src/Servant/Server/Internal/Handler.hs:27:31-41)
Control.Monad.Trans.Resource.runResourceT (./Control/Monad/Trans/Resource.hs:(192,14)-(197,18))
Network.Wai.Handler.Warp.HTTP1.processRequest (./Network/Wai/Handler/Warp/HTTP1.hs:195:20-22)
Network.Wai.Handler.Warp.HTTP1.processRequest (./Network/Wai/Handler/Warp/HTTP1.hs:(195,5)-(203,31))
Network.Wai.Handler.Warp.HTTP1.http1server.loop (./Network/Wai/Handler/Warp/HTTP1.hs:(141,9)-(157,42))
HasCallStack backtrace:
error, called at app/Main.hs:48:32 in backtrace-0.1.0.0-inplace-server:Main
```
The first two entries have been added by `annotateCallStackIO`, defined in `annotateCallStackIO`.
- - - - -
a1567efd by Sylvain Henry at 2025-09-01T23:01:35-04:00
RTS: rely less on Hadrian for flag setting (#25843)
Hadrian used to pass -Dfoo command-line flags directly to build the rts.
We can replace most of these flags with CPP based on cabal flags.
It makes building boot libraries with cabal-install simpler (cf #25843).
- - - - -
ca5b0283 by Sergey Vinokurov at 2025-09-01T23:02:23-04:00
Remove unnecessary irrefutable patterns from Bifunctor instances for tuples
Implementation of https://github.com/haskell/core-libraries-committee/issues/339
Metric Decrease:
mhu-perf
- - - - -
2da84b7a by sheaf at 2025-09-01T23:03:23-04:00
Only use active rules when simplifying rule RHSs
When we are simplifying the RHS of a rule, we make sure to only apply
rewrites from rules that are active throughout the original rule's
range of active phases.
For example, if a rule is always active, we only fire rules that are
themselves always active when simplifying the RHS. Ditto for inline
activations.
This is achieved by setting the simplifier phase to a range of phases,
using the new SimplPhaseRange constructor. Then:
1. When simplifying the RHS of a rule, or of a stable unfolding,
we set the simplifier phase to a range of phases, computed from
the activation of the RULE/unfolding activation, using the
function 'phaseFromActivation'.
The details are explained in Note [What is active in the RHS of a RULE?]
in GHC.Core.Opt.Simplify.Utils.
2. The activation check for other rules and inlinings is then:
does the activation of the other rule/inlining cover the whole
phase range set in sm_phase? This continues to use the 'isActive'
function, which now accounts for phase ranges.
On the way, this commit also moves the exact-print SourceText annotation
from the Activation datatype to the ActivationAnn type. This keeps the
main Activation datatype free of any extra cruft.
Fixes #26323
- - - - -
ccd2023e by Zubin Duggal at 2025-09-02T17:49:23+05:30
compiler: Attempt to systematize Unique tags by introducing an ADT for each different tag
Fixes #26264
- - - - -
527 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .mailmap
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Builtin/PrimOps/Ids.hs
- compiler/GHC/Builtin/Types.hs
- compiler/GHC/Builtin/Types/Prim.hs
- compiler/GHC/Builtin/Uniques.hs
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/InfoTable.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Cmm/Dataflow/Label.hs
- compiler/GHC/Cmm/Info.hs
- compiler/GHC/Cmm/Pipeline.hs
- compiler/GHC/Cmm/UniqueRenamer.hs
- compiler/GHC/CmmToAsm/CFG.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Core/Class.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/CprAnal.hs
- compiler/GHC/Core/Opt/DmdAnal.hs
- compiler/GHC/Core/Opt/Monad.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/Pipeline/Types.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Monad.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Predicate.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/TyCo/Compare.hs
- compiler/GHC/Core/TyCo/Rep.hs
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Core/Unfold.hs
- compiler/GHC/Core/Unfold/Make.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg.hs
- + compiler/GHC/CoreToStg/AddImplicitBinds.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Driver/Config/Finder.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Binds.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Foreign/Call.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Ext/Binary.hs
- compiler/GHC/Iface/Ext/Types.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Recomp/Types.hs
- compiler/GHC/Iface/Rename.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/JS/JStg/Monad.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Platform/Reg.hs
- compiler/GHC/Plugins.hs
- compiler/GHC/Rename/HsType.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Runtime/Debugger/Breakpoints.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Stg/EnforceEpt.hs
- compiler/GHC/Stg/Lint.hs
- compiler/GHC/Stg/Pipeline.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToCmm.hs
- compiler/GHC/StgToCmm/ExtCode.hs
- compiler/GHC/StgToCmm/Monad.hs
- compiler/GHC/StgToCmm/Prim.hs
- compiler/GHC/StgToJS/Prim.hs
- compiler/GHC/StgToJS/StaticPtr.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Expr.hs-boot
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Instance/Class.hs
- compiler/GHC/Tc/Instance/Family.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Build.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types.hs
- − compiler/GHC/Tc/Types/EvTerm.hs
- compiler/GHC/Tc/Types/Evidence.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Concrete.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Demand.hs
- compiler/GHC/Types/Error.hs
- compiler/GHC/Types/Id.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/Name/Cache.hs
- compiler/GHC/Types/Name/Reader.hs
- compiler/GHC/Types/RepType.hs
- compiler/GHC/Types/SptEntry.hs
- compiler/GHC/Types/TyThing.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Unique/DSM.hs
- compiler/GHC/Types/Unique/Supply.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Error.hs
- compiler/ghc.cabal.in
- configure.ac
- − docs/users_guide/9.14.1-notes.rst
- + docs/users_guide/9.16.1-notes.rst
- docs/users_guide/eventlog-formats.rst
- docs/users_guide/release-notes.rst
- docs/users_guide/separate_compilation.rst
- ghc/GHCi/UI.hs
- ghc/ghc-bin.cabal.in
- hadrian/bootstrap/generate_bootstrap_plans
- hadrian/bootstrap/hadrian-bootstrap-gen.cabal
- hadrian/bootstrap/plan-9_10_1.json
- hadrian/bootstrap/plan-9_6_5.json → hadrian/bootstrap/plan-9_10_2.json
- hadrian/bootstrap/plan-9_6_6.json → hadrian/bootstrap/plan-9_12_1.json
- hadrian/bootstrap/plan-9_6_4.json → hadrian/bootstrap/plan-9_12_2.json
- − hadrian/bootstrap/plan-9_6_1.json
- − hadrian/bootstrap/plan-9_6_2.json
- − hadrian/bootstrap/plan-9_6_3.json
- − hadrian/bootstrap/plan-9_8_1.json
- − hadrian/bootstrap/plan-9_8_2.json
- hadrian/bootstrap/plan-bootstrap-9_10_1.json
- hadrian/bootstrap/plan-bootstrap-9_6_5.json → hadrian/bootstrap/plan-bootstrap-9_10_2.json
- hadrian/bootstrap/plan-bootstrap-9_6_6.json → hadrian/bootstrap/plan-bootstrap-9_12_1.json
- hadrian/bootstrap/plan-bootstrap-9_8_1.json → hadrian/bootstrap/plan-bootstrap-9_12_2.json
- − hadrian/bootstrap/plan-bootstrap-9_6_1.json
- − hadrian/bootstrap/plan-bootstrap-9_6_2.json
- − hadrian/bootstrap/plan-bootstrap-9_6_3.json
- − hadrian/bootstrap/plan-bootstrap-9_6_4.json
- − hadrian/bootstrap/plan-bootstrap-9_8_2.json
- hadrian/bootstrap/src/Main.hs
- hadrian/hadrian.cabal
- hadrian/src/Rules/ToolArgs.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Packages.hs
- hie.yaml
- libffi-tarballs
- libraries/Cabal
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Data/Bifunctor.hs
- libraries/base/src/GHC/Exts.hs
- − libraries/base/src/GHC/IOPort.hs
- libraries/base/src/GHC/Stack/CloneStack.hs
- libraries/directory
- libraries/ghc-bignum/changelog.md
- libraries/ghc-boot-th/GHC/Boot/TH/Ppr.hs
- libraries/ghc-experimental/ghc-experimental.cabal.in
- + libraries/ghc-experimental/src/GHC/Exception/Backtrace/Experimental.hs
- + libraries/ghc-experimental/src/GHC/Stack/Annotation/Experimental.hs
- libraries/ghc-heap/GHC/Exts/Heap/ClosureTypes.hs
- libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
- + libraries/ghc-heap/GHC/Exts/Heap/Constants.hs
- + libraries/ghc-heap/GHC/Exts/Heap/InfoTable.hs
- + libraries/ghc-heap/GHC/Exts/Heap/InfoTable/Types.hs
- + libraries/ghc-heap/GHC/Exts/Heap/InfoTableProf.hs
- libraries/ghc-heap/GHC/Exts/Heap/ProfInfo/Types.hs
- libraries/ghc-heap/GHC/Exts/Stack.hs
- + libraries/ghc-heap/GHC/Exts/Stack/Constants.hs
- libraries/ghc-heap/GHC/Exts/Stack/Decode.hs
- libraries/ghc-heap/ghc-heap.cabal.in
- libraries/ghc-heap/cbits/HeapPrim.cmm → libraries/ghc-internal/cbits/HeapPrim.cmm
- libraries/ghc-heap/cbits/Stack.cmm → libraries/ghc-internal/cbits/Stack.cmm
- libraries/ghc-internal/cbits/StackCloningDecoding.cmm
- libraries/ghc-heap/cbits/Stack_c.c → libraries/ghc-internal/cbits/Stack_c.c
- libraries/ghc-internal/cbits/pdep.c
- libraries/ghc-internal/cbits/pext.c
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/jsbits/base.js
- libraries/ghc-internal/src/GHC/Internal/Bignum/Natural.hs
- libraries/ghc-internal/src/GHC/Internal/ClosureTypes.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows.hsc
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Exception.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Backtrace.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Exts.hs
- + libraries/ghc-internal/src/GHC/Internal/Heap/Closures.hs
- libraries/ghc-heap/GHC/Exts/Heap/Constants.hsc → libraries/ghc-internal/src/GHC/Internal/Heap/Constants.hsc
- libraries/ghc-heap/GHC/Exts/Heap/InfoTable.hsc → libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable.hsc
- libraries/ghc-heap/GHC/Exts/Heap/InfoTable/Types.hsc → libraries/ghc-internal/src/GHC/Internal/Heap/InfoTable/Types.hsc
- libraries/ghc-heap/GHC/Exts/Heap/InfoTableProf.hsc → libraries/ghc-internal/src/GHC/Internal/Heap/InfoTableProf.hsc
- + libraries/ghc-internal/src/GHC/Internal/Heap/ProfInfo/Types.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Buffer.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Windows/Handle.hsc
- − libraries/ghc-internal/src/GHC/Internal/IOPort.hs
- libraries/ghc-internal/src/GHC/Internal/Prim/PtrEq.hs
- + libraries/ghc-internal/src/GHC/Internal/Stack/Annotation.hs
- libraries/ghc-internal/src/GHC/Internal/Stack/CloneStack.hs
- libraries/ghc-heap/GHC/Exts/Stack/Constants.hsc → libraries/ghc-internal/src/GHC/Internal/Stack/Constants.hsc
- + libraries/ghc-internal/src/GHC/Internal/Stack/Decode.hs
- libraries/ghc-internal/src/GHC/Internal/System/Posix/Internals.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lib.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Lift.hs
- libraries/ghc-internal/src/GHC/Internal/TH/Syntax.hs
- + libraries/ghc-internal/tests/Makefile
- + libraries/ghc-internal/tests/all.T
- + libraries/ghc-internal/tests/backtraces/Makefile
- + libraries/ghc-internal/tests/backtraces/T14532a.hs
- + libraries/ghc-internal/tests/backtraces/T14532a.stdout
- + libraries/ghc-internal/tests/backtraces/T14532b.hs
- + libraries/ghc-internal/tests/backtraces/T14532b.stdout
- + libraries/ghc-internal/tests/backtraces/all.T
- + libraries/ghc-internal/tests/stack-annotation/Makefile
- + libraries/ghc-internal/tests/stack-annotation/TestUtils.hs
- + libraries/ghc-internal/tests/stack-annotation/all.T
- + libraries/ghc-internal/tests/stack-annotation/ann_frame001.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame001.stdout
- + libraries/ghc-internal/tests/stack-annotation/ann_frame002.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame002.stdout
- + libraries/ghc-internal/tests/stack-annotation/ann_frame003.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame003.stdout
- + libraries/ghc-internal/tests/stack-annotation/ann_frame004.hs
- + libraries/ghc-internal/tests/stack-annotation/ann_frame004.stdout
- libraries/ghc-prim/changelog.md
- libraries/ghci/GHCi/CreateBCO.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/TH.hs
- libraries/ghci/ghci.cabal.in
- libraries/hpc
- libraries/template-haskell/Language/Haskell/TH/Lib.hs
- libraries/template-haskell/Language/Haskell/TH/Quote.hs
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- libraries/template-haskell/changelog.md
- libraries/template-haskell/tests/all.T
- libraries/time
- libraries/unix
- m4/find_python.m4
- rts/CloneStack.c
- rts/CloneStack.h
- rts/ClosureFlags.c
- rts/Disassembler.c
- rts/Hash.c
- rts/Interpreter.c
- rts/LdvProfile.c
- rts/Messages.c
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/Printer.c
- rts/RaiseAsync.c
- rts/RetainerProfile.c
- rts/RtsMessages.c
- rts/RtsSymbols.c
- rts/RtsUtils.c
- rts/STM.c
- rts/StgMiscClosures.cmm
- rts/Trace.c
- rts/TraverseHeap.c
- rts/Updates.h
- rts/external-symbols.list.in
- rts/include/rts/storage/ClosureTypes.h
- rts/include/rts/storage/Closures.h
- rts/include/stg/MiscClosures.h
- rts/include/stg/SMP.h
- rts/js/mem.js
- rts/js/profiling.js
- rts/posix/ticker/Pthread.c
- rts/posix/ticker/TimerFd.c
- rts/rts.cabal
- rts/sm/Compact.c
- rts/sm/Evac.c
- rts/sm/NonMovingMark.c
- rts/sm/Sanity.c
- rts/sm/Scav.c
- rts/win32/AsyncWinIO.c
- rts/win32/libHSghc-internal.def
- testsuite/.gitignore
- testsuite/config/ghc
- testsuite/driver/testlib.py
- testsuite/tests/arrows/should_compile/T21301.stderr
- testsuite/tests/core-to-stg/T24124.stderr
- testsuite/tests/corelint/LintEtaExpand.stderr
- testsuite/tests/deSugar/should_compile/T2431.stderr
- testsuite/tests/deSugar/should_fail/DsStrictFail.stderr
- testsuite/tests/deSugar/should_run/T20024.stderr
- testsuite/tests/deSugar/should_run/dsrun005.stderr
- testsuite/tests/deSugar/should_run/dsrun007.stderr
- testsuite/tests/deSugar/should_run/dsrun008.stderr
- testsuite/tests/deriving/should_run/T9576.stderr
- testsuite/tests/dmdanal/should_compile/T16029.stdout
- testsuite/tests/dmdanal/sigs/T21119.stderr
- testsuite/tests/dmdanal/sigs/T21888.stderr
- + testsuite/tests/driver/make-prim/GHC/Internal/Prim.hs
- + testsuite/tests/driver/make-prim/Makefile
- + testsuite/tests/driver/make-prim/Test.hs
- + testsuite/tests/driver/make-prim/Test2.hs
- + testsuite/tests/driver/make-prim/all.T
- testsuite/tests/gadt/T12468.stderr
- testsuite/tests/ghc-e/should_fail/T24172.stderr
- testsuite/tests/ghci.debugger/scripts/break011.stdout
- testsuite/tests/ghci.debugger/scripts/break024.stdout
- testsuite/tests/ghci/scripts/Defer02.stderr
- testsuite/tests/ghci/scripts/T15325.stderr
- testsuite/tests/ghci/scripts/T8353.stderr
- testsuite/tests/ghci/scripts/ghci038.stdout
- testsuite/tests/hpc/recsel/recsel.hs
- testsuite/tests/hpc/recsel/recsel.stdout
- testsuite/tests/indexed-types/should_compile/T2238.hs
- testsuite/tests/indexed-types/should_fail/T5439.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout
- testsuite/tests/interface-stability/ghc-experimental-exports.stdout-mingw32
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- − testsuite/tests/lib/stm/T26028.hs
- − testsuite/tests/lib/stm/T26028.stdout
- − testsuite/tests/lib/stm/all.T
- + testsuite/tests/llvm/should_run/T20645.hs
- + testsuite/tests/llvm/should_run/T20645.stdout
- testsuite/tests/llvm/should_run/all.T
- − testsuite/tests/module/T21752.stderr
- testsuite/tests/module/mod150.stderr
- testsuite/tests/module/mod151.stderr
- testsuite/tests/module/mod152.stderr
- testsuite/tests/module/mod153.stderr
- testsuite/tests/numeric/should_compile/T15547.stderr
- testsuite/tests/numeric/should_compile/T23907.stderr
- + testsuite/tests/numeric/should_run/T18619.hs
- + testsuite/tests/numeric/should_run/T18619.stderr
- + testsuite/tests/numeric/should_run/T26230.hs
- + testsuite/tests/numeric/should_run/T26230.stdout
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/overloadedrecflds/should_fail/T18999_NoDisambiguateRecordFields.stderr
- + testsuite/tests/overloadedrecflds/should_run/T26295.hs
- + testsuite/tests/overloadedrecflds/should_run/T26295.stdout
- testsuite/tests/overloadedrecflds/should_run/all.T
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- testsuite/tests/parser/should_compile/T19082.stderr
- testsuite/tests/partial-sigs/should_compile/T10403.stderr
- testsuite/tests/partial-sigs/should_fail/T10615.stderr
- + testsuite/tests/patsyn/should_compile/T26331.hs
- + testsuite/tests/patsyn/should_compile/T26331a.hs
- testsuite/tests/patsyn/should_compile/all.T
- testsuite/tests/patsyn/should_run/ghci.stderr
- testsuite/tests/perf/compiler/T4007.stdout
- testsuite/tests/perf/compiler/hard_hole_fits.stderr
- testsuite/tests/plugins/Makefile
- + testsuite/tests/plugins/T21730-plugin/Makefile
- + testsuite/tests/plugins/T21730-plugin/Setup.hs
- + testsuite/tests/plugins/T21730-plugin/T21730-plugin.cabal
- + testsuite/tests/plugins/T21730-plugin/T21730_Plugin.hs
- + testsuite/tests/plugins/T21730.hs
- testsuite/tests/plugins/all.T
- testsuite/tests/primops/should_run/UnliftedIOPort.hs
- testsuite/tests/primops/should_run/all.T
- testsuite/tests/quasiquotation/T4491/test.T
- testsuite/tests/quotes/LiftErrMsg.stderr
- testsuite/tests/quotes/LiftErrMsgDefer.stderr
- testsuite/tests/quotes/LiftErrMsgTyped.stderr
- testsuite/tests/rename/should_compile/T22513d.stderr
- testsuite/tests/rename/should_compile/T22513e.stderr
- testsuite/tests/rename/should_compile/T22513f.stderr
- testsuite/tests/rename/should_compile/T22513g.stderr
- testsuite/tests/rename/should_compile/T22513h.stderr
- testsuite/tests/rename/should_compile/T22513i.stderr
- testsuite/tests/rename/should_compile/rn039.ghc.stderr
- testsuite/tests/rename/should_fail/T15487.stderr
- testsuite/tests/rename/should_fail/T18740a.stderr
- testsuite/tests/rename/should_fail/rnfail044.stderr
- + testsuite/tests/rep-poly/NoEtaRequired.hs
- testsuite/tests/rep-poly/T21906.stderr
- testsuite/tests/rep-poly/all.T
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/rts/all.T
- testsuite/tests/rts/flags/all.T
- testsuite/tests/safeHaskell/flags/SafeFlags17.stderr
- testsuite/tests/safeHaskell/safeLanguage/SafeLang15.stderr
- testsuite/tests/simplCore/should_compile/DataToTagFamilyScrut.stderr
- testsuite/tests/simplCore/should_compile/T15056.stderr
- testsuite/tests/simplCore/should_compile/T15205.stderr
- testsuite/tests/simplCore/should_compile/T15445.stderr
- testsuite/tests/simplCore/should_compile/T17366.stderr
- testsuite/tests/simplCore/should_compile/T17966.stderr
- testsuite/tests/simplCore/should_compile/T22309.stderr
- testsuite/tests/simplCore/should_compile/T22375DataFamily.stderr
- testsuite/tests/simplCore/should_compile/T23307.stderr
- testsuite/tests/simplCore/should_compile/T23307a.stderr
- + testsuite/tests/simplCore/should_compile/T24606.hs
- testsuite/tests/simplCore/should_compile/T25389.stderr
- testsuite/tests/simplCore/should_compile/T25713.stderr
- + testsuite/tests/simplCore/should_compile/T26323b.hs
- testsuite/tests/simplCore/should_compile/T7360.stderr
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T26323.hs
- + testsuite/tests/simplCore/should_run/T26323.stdout
- testsuite/tests/simplCore/should_run/all.T
- testsuite/tests/simplStg/should_compile/T15226b.stderr
- testsuite/tests/tcplugins/CtIdPlugin.hs
- testsuite/tests/th/Makefile
- testsuite/tests/th/T10267.stderr
- testsuite/tests/th/T14627.stderr
- testsuite/tests/th/T15321.stderr
- + testsuite/tests/th/TH_Depends_Dir.hs
- + testsuite/tests/th/TH_Depends_Dir.stdout
- + testsuite/tests/th/TH_Depends_Dir_External.hs
- testsuite/tests/th/all.T
- testsuite/tests/type-data/should_run/T22332a.stderr
- testsuite/tests/typecheck/should_compile/Makefile
- testsuite/tests/typecheck/should_compile/T12763.stderr
- testsuite/tests/typecheck/should_compile/T13050.stderr
- testsuite/tests/typecheck/should_compile/T14273.stderr
- testsuite/tests/typecheck/should_compile/T14590.stderr
- testsuite/tests/typecheck/should_compile/T14774.stdout
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- testsuite/tests/typecheck/should_compile/T25180.stderr
- + testsuite/tests/typecheck/should_compile/T25992a.hs
- + testsuite/tests/typecheck/should_compile/T26225.hs
- + testsuite/tests/typecheck/should_compile/T26225b.hs
- + testsuite/tests/typecheck/should_compile/T26345.hs
- + testsuite/tests/typecheck/should_compile/T26346.hs
- + testsuite/tests/typecheck/should_compile/T26350.hs
- + testsuite/tests/typecheck/should_compile/T26358.hs
- testsuite/tests/typecheck/should_compile/T9497a.stderr
- testsuite/tests/typecheck/should_compile/all.T
- testsuite/tests/typecheck/should_compile/refinement_hole_fits.stderr
- testsuite/tests/typecheck/should_compile/subsumption_sort_hole_fits.stderr
- − testsuite/tests/typecheck/should_fail/T12563.stderr
- testsuite/tests/typecheck/should_fail/T14618.stderr
- testsuite/tests/typecheck/should_fail/T14884.stderr
- testsuite/tests/typecheck/should_fail/T21130.stderr
- testsuite/tests/typecheck/should_fail/T23739b.stderr
- testsuite/tests/typecheck/should_fail/T23739c.stderr
- + testsuite/tests/typecheck/should_fail/T26318.hs
- + testsuite/tests/typecheck/should_fail/T26318.stderr
- testsuite/tests/typecheck/should_fail/T6022.stderr
- testsuite/tests/typecheck/should_fail/T8883.stderr
- testsuite/tests/typecheck/should_fail/T9497d.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_fail/tcfail037.stderr
- testsuite/tests/typecheck/should_fail/tcfail140.stderr
- testsuite/tests/typecheck/should_run/T10284.stderr
- testsuite/tests/typecheck/should_run/T13838.stderr
- testsuite/tests/typecheck/should_run/T9497a-run.stderr
- testsuite/tests/typecheck/should_run/T9497b-run.stderr
- testsuite/tests/typecheck/should_run/T9497c-run.stderr
- testsuite/tests/unboxedsums/unpack_sums_7.stdout
- testsuite/tests/unsatisfiable/T23816.stderr
- testsuite/tests/unsatisfiable/UnsatDefer.stderr
- testsuite/tests/vdq-rta/should_fail/T23738_fail_pun.stderr
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- testsuite/tests/wasm/should_run/control-flow/RunWasm.hs
- utils/check-exact/ExactPrint.hs
- utils/deriveConstants/Main.hs
- utils/genprimopcode/Lexer.x
- utils/genprimopcode/Main.hs
- utils/genprimopcode/Parser.y
- utils/genprimopcode/ParserM.hs
- utils/genprimopcode/Syntax.hs
- utils/haddock/haddock-api/src/Haddock/InterfaceFile.hs
- utils/jsffi/dyld.mjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/742e29e001e25e99d4d3e3395d970d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/742e29e001e25e99d4d3e3395d970d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/9.12.3-backports] 9 commits: CprAnal: Detect recursive newtypes (#25944)
by Zubin (@wz1000) 02 Sep '25
by Zubin (@wz1000) 02 Sep '25
02 Sep '25
Zubin pushed to branch wip/9.12.3-backports at Glasgow Haskell Compiler / GHC
Commits:
24710c4c by Sebastian Graf at 2025-09-02T17:19:41+05:30
CprAnal: Detect recursive newtypes (#25944)
While `cprTransformDataConWork` handles recursive data con workers, it
did not detect the case when a newtype is responsible for the recursion.
This is now detected in the `Cast` case of `cprAnal`.
The same reproducer made it clear that `isRecDataCon` lacked congruent
handling for `AppTy` and `CastTy`, now fixed.
Furthermore, the new repro case T25944 triggered this bug via an
infinite loop in `cprFix`, caused by the infelicity in `isRecDataCon`.
While it should be much less likely to trigger such an infinite loop now
that `isRecDataCon` has been fixed, I made sure to abort the loop after
10 iterations and emitting a warning instead.
Fixes #25944.
(cherry picked from commit 4bc78496406f7469640faaa46e2f311c05760124)
- - - - -
aa52a199 by Zubin Duggal at 2025-09-02T17:19:41+05:30
fetch_gitlab: Ensure we copy users_guide.pdf and Haddock.pdf to the release docs directory
Fixes #24093
(cherry picked from commit 9fa590a6e27545995cdcf419ed7a6504e6668b18)
- - - - -
ac9ab53d by Ben Gamari at 2025-09-02T17:19:41+05:30
configure: Allow override of CrossCompiling
As noted in #26236, the current inference logic is a bit simplistic. In
particular, there are many cases (e.g. building for a new libc) where
the target and host triples may differ yet we are still able to run the
produced artifacts as native code.
Closes #26236.
(cherry picked from commit 81577fe7c1913c53608bf03e48f84507be904620)
- - - - -
d2b40901 by Simon Peyton Jones at 2025-09-02T17:19:41+05:30
Take more care in zonkEqTypes on AppTy/AppTy
This patch fixes #26256.
See Note [zonkEqTypes and the PKTI] in GHC.Tc.Solver.Equality
(cherry picked from commit 18036d5205ac648bb245217519fed2fd931a9982)
- - - - -
2b0f2f43 by Andreas Klebinger at 2025-09-02T17:19:41+05:30
Make unexpected LLVM versions a warning rather than an error.
Typically a newer LLVM version *will* work so erroring out if
a user uses a newer LLVM version is too aggressive.
Fixes #25915
(cherry picked from commit 50842f83f467ff54dd22470559a7af79d2025c03)
- - - - -
68a1a88f by Teo Camarasu at 2025-09-02T17:19:41+05:30
rts: spin if we see a WHITEHOLE in messageBlackHole
When a BLACKHOLE gets cancelled in raiseAsync, we indirect to a THUNK.
GC can then shortcut this, replacing our BLACKHOLE with a fresh THUNK.
This THUNK is not guaranteed to have a valid indirectee field.
If at the same time, a message intended for the previous BLACKHOLE is
processed and concurrently we BLACKHOLE the THUNK, thus temporarily
turning it into a WHITEHOLE, we can get a segfault, since we look at the
undefined indirectee field of the THUNK
The fix is simple: spin if we see a WHITEHOLE, and it will soon be
replaced with a valid BLACKHOLE.
Resolves #26205
(cherry picked from commit 4021181ee0860aca2054883a531f3312361cc701)
- - - - -
670cbe9d by Teo Camarasu at 2025-09-02T17:19:41+05:30
rts: ensure MessageBlackHole.link is always a valid closure
We turn a MessageBlackHole into an StgInd in wakeBlockingQueue().
Therefore it's important that the link field, which becomes the
indirection field, always points to a valid closure.
It's unclear whether it's currently possible for the previous behaviour
to lead to a crash, but it's good to be consistent about this invariant nonetheless.
Co-authored-by: Andreas Klebinger <klebinger.andreas(a)gmx.at>
(cherry picked from commit a8b2fbae6bcf20bc2f3fe58803096d2a9c5fc43d)
- - - - -
ab0a766c by Reed Mullanix at 2025-09-02T17:19:41+05:30
ghc-internal: Fix naturalAndNot for NB/NS case
When the first argument to `naturalAndNot` is larger than a `Word` and the second is `Word`-sized, `naturalAndNot` will truncate the
result:
```
>>> naturalAndNot ((2 ^ 65) .|. (2 ^ 3)) (2 ^ 3)
0
```
In contrast, `naturalAndNot` does not truncate when both arguments are larger than a `Word`, so this appears to be a bug.
Luckily, the fix is pretty easy: we just need to call `bigNatAndNotWord#` instead of truncating.
Fixes #26230
(cherry picked from commit a766286fe759251eceb304c54ba52841c2a51f86)
- - - - -
9edb71d5 by Ben Gamari at 2025-09-02T17:19:41+05:30
llvmGen: Fix built-in variable predicate
Previously the predicate to identify LLVM builtin global variables was
checking for `$llvm` rather than `@llvm` as it should.
(cherry picked from commit 6e67fa083a50684e1cfae546e07cab4d4250e871)
- - - - -
24 changed files:
- .gitlab/rel_eng/fetch-gitlab-artifacts/fetch_gitlab.py
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/Core/Opt/CprAnal.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Tc/Solver/Equality.hs
- configure.ac
- libraries/base/changelog.md
- libraries/ghc-bignum/changelog.md
- libraries/ghc-bignum/src/GHC/Num/Natural.hs
- rts/Messages.c
- rts/StgMiscClosures.cmm
- rts/Updates.h
- + testsuite/tests/cpranal/sigs/T25944.hs
- + testsuite/tests/cpranal/sigs/T25944.stderr
- testsuite/tests/cpranal/sigs/all.T
- + testsuite/tests/numeric/should_run/T26230.hs
- + testsuite/tests/numeric/should_run/T26230.stdout
- testsuite/tests/numeric/should_run/all.T
- + testsuite/tests/partial-sigs/should_compile/T26256.hs
- + testsuite/tests/partial-sigs/should_compile/T26256.stderr
- testsuite/tests/partial-sigs/should_compile/all.T
- + testsuite/tests/typecheck/should_compile/T26256a.hs
- testsuite/tests/typecheck/should_compile/all.T
Changes:
=====================================
.gitlab/rel_eng/fetch-gitlab-artifacts/fetch_gitlab.py
=====================================
@@ -134,6 +134,9 @@ def fetch_artifacts(release: str, pipeline_id: int,
logging.info(f'extracted docs {f} to {dest}')
index_path = destdir / 'docs' / 'index.html'
index_path.replace(dest / 'index.html')
+ pdfs = list(destdir.glob('*.pdf'))
+ for f in pdfs:
+ f.replace(dest / f.name)
elif job.name == 'hackage-doc-tarball':
dest = dest_dir / 'hackage_docs'
logging.info(f'moved hackage_docs to {dest}')
=====================================
compiler/GHC/CmmToLlvm/Base.hs
=====================================
@@ -526,10 +526,10 @@ generateExternDecls = do
modifyEnv $ \env -> env { envAliases = emptyUniqSet }
return (concat defss, [])
--- | Is a variable one of the special @$llvm@ globals?
+-- | Is a variable one of the special @\@llvm@ globals?
isBuiltinLlvmVar :: LlvmVar -> Bool
isBuiltinLlvmVar (LMGlobalVar lbl _ _ _ _ _) =
- "$llvm" `isPrefixOf` unpackFS lbl
+ "llvm." `isPrefixOf` unpackFS lbl
isBuiltinLlvmVar _ = False
-- | Here we take a global variable definition, rename it with a
=====================================
compiler/GHC/Core/Opt/CprAnal.hs
=====================================
@@ -1,3 +1,4 @@
+{-# LANGUAGE MultiWayIf #-}
-- | Constructed Product Result analysis. Identifies functions that surely
-- return heap-allocated records on every code path, so that we can eliminate
@@ -22,12 +23,15 @@ import GHC.Types.Demand
import GHC.Types.Cpr
import GHC.Types.Unique.MemoFun
+import GHC.Core
import GHC.Core.FamInstEnv
import GHC.Core.DataCon
import GHC.Core.Type
import GHC.Core.Utils
-import GHC.Core
+import GHC.Core.Coercion
+import GHC.Core.Reduction
import GHC.Core.Seq
+import GHC.Core.TyCon
import GHC.Core.Opt.WorkWrap.Utils
import GHC.Data.Graph.UnVar -- for UnVarSet
@@ -216,9 +220,13 @@ cprAnal' _ (Type ty) = (topCprType, Type ty) -- Doesn't happen, in fact
cprAnal' _ (Coercion co) = (topCprType, Coercion co)
cprAnal' env (Cast e co)
- = (cpr_ty, Cast e' co)
+ = (cpr_ty', Cast e' co)
where
(cpr_ty, e') = cprAnal env e
+ cpr_ty'
+ | cpr_ty == topCprType = topCprType -- cheap case first
+ | isRecNewTyConApp env (coercionRKind co) = topCprType -- See Note [CPR for recursive data constructors]
+ | otherwise = cpr_ty
cprAnal' env (Tick t e)
= (cpr_ty, Tick t e')
@@ -384,6 +392,19 @@ cprTransformDataConWork env con args
mAX_CPR_SIZE :: Arity
mAX_CPR_SIZE = 10
+isRecNewTyConApp :: AnalEnv -> Type -> Bool
+-- See Note [CPR for recursive newtype constructors]
+isRecNewTyConApp env ty
+ --- | pprTrace "isRecNewTyConApp" (ppr ty) False = undefined
+ | Just (tc, tc_args) <- splitTyConApp_maybe ty =
+ if | Just (HetReduction (Reduction _ rhs) _) <- topReduceTyFamApp_maybe (ae_fam_envs env) tc tc_args
+ -> isRecNewTyConApp env rhs
+ | Just dc <- newTyConDataCon_maybe tc
+ -> ae_rec_dc env dc == DefinitelyRecursive
+ | otherwise
+ -> False
+ | otherwise = False
+
--
-- * Bindings
--
@@ -407,12 +428,18 @@ cprFix orig_env orig_pairs
| otherwise = orig_pairs
init_env = extendSigEnvFromIds orig_env (map fst init_pairs)
+ -- If fixed-point iteration does not yield a result we use this instead
+ -- See Note [Safe abortion in the fixed-point iteration]
+ abort :: (AnalEnv, [(Id,CoreExpr)])
+ abort = step (nonVirgin orig_env) [(setIdCprSig id topCprSig, rhs) | (id, rhs) <- orig_pairs ]
+
-- The fixed-point varies the idCprSig field of the binders and and their
-- entries in the AnalEnv, and terminates if that annotation does not change
-- any more.
loop :: Int -> AnalEnv -> [(Id,CoreExpr)] -> (AnalEnv, [(Id,CoreExpr)])
loop n env pairs
| found_fixpoint = (reset_env', pairs')
+ | n == 10 = pprTraceUserWarning (text "cprFix aborts. This is not terrible, but worth reporting a GHC issue." <+> ppr (map fst pairs)) $ abort
| otherwise = loop (n+1) env' pairs'
where
-- In all but the first iteration, delete the virgin flag
@@ -511,8 +538,9 @@ cprAnalBind env id rhs
-- possibly trim thunk CPR info
rhs_ty'
-- See Note [CPR for thunks]
- | stays_thunk = trimCprTy rhs_ty
- | otherwise = rhs_ty
+ | rhs_ty == topCprType = topCprType -- cheap case first
+ | stays_thunk = trimCprTy rhs_ty
+ | otherwise = rhs_ty
-- See Note [Arity trimming for CPR signatures]
sig = mkCprSigForArity (idArity id) rhs_ty'
-- See Note [OPAQUE pragma]
@@ -631,7 +659,7 @@ data AnalEnv
, ae_fam_envs :: FamInstEnvs
-- ^ Needed when expanding type families and synonyms of product types.
, ae_rec_dc :: DataCon -> IsRecDataConResult
- -- ^ Memoised result of 'GHC.Core.Opt.WorkWrap.Utils.isRecDataCon'
+ -- ^ Memoised result of 'GHC.Core.Opt.WorkWrap.Utils.isRecDataType
}
instance Outputable AnalEnv where
@@ -1034,10 +1062,11 @@ Eliminating the shared 'c' binding in the process. And then
What can we do about it?
- A. Don't CPR functions that return a *recursive data type* (the list in this
- case). This is the solution we adopt. Rationale: the benefit of CPR on
- recursive data structures is slight, because it only affects the outer layer
- of a potentially massive data structure.
+ A. Don't give recursive data constructors or casts representing recursive newtype constructors
+ the CPR property (the list in this case). This is the solution we adopt.
+ Rationale: the benefit of CPR on recursive data structures is slight,
+ because it only affects the outer layer of a potentially massive data
+ structure.
B. Don't CPR any *recursive function*. That would be quite conservative, as it
would also affect e.g. the factorial function.
C. Flat CPR only for recursive functions. This prevents the asymptotic
@@ -1047,10 +1076,15 @@ What can we do about it?
`c` in the second eqn of `replicateC`). But we'd need to know which paths
were hot. We want such static branch frequency estimates in #20378.
-We adopt solution (A) It is ad-hoc, but appears to work reasonably well.
-Deciding what a "recursive data constructor" is is quite tricky and ad-hoc, too:
-See Note [Detecting recursive data constructors]. We don't have to be perfect
-and can simply keep on unboxing if unsure.
+We adopt solution (A). It is ad-hoc, but appears to work reasonably well.
+Specifically:
+
+* For data constructors, in `cprTransformDataConWork` we check for a recursive
+ data constructor by calling `ae_rec_dc env`, which is just a memoised version
+ of `isRecDataCon`. See Note [Detecting recursive data constructors]
+* For newtypes, in the `Cast` case of `cprAnal`, we check for a recursive newtype
+ by calling `isRecNewTyConApp`, which in turn calls `ae_rec_dc env`.
+ See Note [CPR for recursive newtype constructors]
Note [Detecting recursive data constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1067,12 +1101,15 @@ looks inside the following class of types, represented by `ty` (and responds
types of its data constructors and check `tc_args` for recursion.
C. If `ty = F tc_args`, `F` is a `FamTyCon` and we can reduce `F tc_args` to
`rhs`, look into the `rhs` type.
+ D. If `ty = f a`, then look into `f` and `a`
+ E. If `ty = ty' |> co`, then look into `ty'`
A few perhaps surprising points:
1. It deems any function type as non-recursive, because it's unlikely that
a recursion through a function type builds up a recursive data structure.
- 2. It doesn't look into kinds or coercion types because there's nothing to unbox.
+ 2. It doesn't look into kinds, literals or coercion types because we are
+ ultimately looking for value-level recursion.
Same for promoted data constructors.
3. We don't care whether an AlgTyCon app `T tc_args` is fully saturated or not;
we simply look at its definition/DataCons and its field tys and look for
@@ -1145,6 +1182,22 @@ I've played with the idea to make points (1) through (3) of 'isRecDataCon'
configurable like (4) to enable more re-use throughout the compiler, but haven't
found a killer app for that yet, so ultimately didn't do that.
+Note [CPR for recursive newtype constructors]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+A newtype constructor is considered recursive iff the data constructor of the
+equivalent datatype definition is recursive.
+See Note [CPR for recursive data constructors].
+Detection is a bit complicated by the fact that newtype constructor applications
+reflect as Casts in Core:
+
+ newtype List a = C (Maybe (a, List a))
+ xs = C (Just (0, C Nothing))
+ ==> {desugar to Core}
+ xs = Just (0, Nothing |> sym N:List) |> sym N:List
+
+So the check for `isRecNewTyConApp` is in the Cast case of `cprAnal` rather than
+in `cprTransformDataConWork` as for data constructors.
+
Note [CPR examples]
~~~~~~~~~~~~~~~~~~~
Here are some examples (stranal/should_compile/T10482a) of the
=====================================
compiler/GHC/Core/Opt/WorkWrap/Utils.hs
=====================================
@@ -63,6 +63,7 @@ import Data.List ( unzip4 )
import GHC.Types.RepType
import GHC.Unit.Types
+import GHC.Core.TyCo.Rep
{-
************************************************************************
@@ -1426,23 +1427,29 @@ isRecDataCon fam_envs fuel orig_dc
| arg_ty <- map scaledThing (dataConRepArgTys dc) ]
go_arg_ty :: IntWithInf -> TyConSet -> Type -> IsRecDataConResult
- go_arg_ty fuel visited_tcs ty
- --- | pprTrace "arg_ty" (ppr ty) False = undefined
+ go_arg_ty fuel visited_tcs ty = -- pprTrace "arg_ty" (ppr ty) $
+ case coreFullView ty of
+ TyConApp tc tc_args -> go_tc_app fuel visited_tcs tc tc_args
+ -- See Note [Detecting recursive data constructors], points (B) and (C)
- | Just (_tcv, ty') <- splitForAllTyCoVar_maybe ty
- = go_arg_ty fuel visited_tcs ty'
+ ForAllTy _ ty' -> go_arg_ty fuel visited_tcs ty'
-- See Note [Detecting recursive data constructors], point (A)
- | Just (tc, tc_args) <- splitTyConApp_maybe ty
- = go_tc_app fuel visited_tcs tc tc_args
+ CastTy ty' _ -> go_arg_ty fuel visited_tcs ty'
- | otherwise
- = NonRecursiveOrUnsure
+ AppTy f a -> go_arg_ty fuel visited_tcs f `combineIRDCR` go_arg_ty fuel visited_tcs a
+ -- See Note [Detecting recursive data constructors], point (D)
+
+ FunTy{} -> NonRecursiveOrUnsure
+ -- See Note [Detecting recursive data constructors], point (1)
+
+ -- (TyVarTy{} | LitTy{} | CastTy{})
+ _ -> NonRecursiveOrUnsure
go_tc_app :: IntWithInf -> TyConSet -> TyCon -> [Type] -> IsRecDataConResult
go_tc_app fuel visited_tcs tc tc_args =
case tyConDataCons_maybe tc of
- --- | pprTrace "tc_app" (vcat [ppr tc, ppr tc_args]) False = undefined
+ ---_ | pprTrace "tc_app" (vcat [ppr tc, ppr tc_args]) False -> undefined
_ | Just (HetReduction (Reduction _ rhs) _) <- topReduceTyFamApp_maybe fam_envs tc tc_args
-- This is the only place where we look at tc_args, which might have
-- See Note [Detecting recursive data constructors], point (C) and (5)
=====================================
compiler/GHC/Driver/Errors/Ppr.hs
=====================================
@@ -276,7 +276,7 @@ instance Diagnostic DriverMessage where
++ llvmVersionStr supportedLlvmVersionLowerBound
++ " and "
++ llvmVersionStr supportedLlvmVersionUpperBound
- ++ ") and reinstall GHC to make -fllvm work")
+ ++ ") and reinstall GHC to ensure -fllvm works")
diagnosticReason = \case
DriverUnknownMessage m
@@ -347,7 +347,7 @@ instance Diagnostic DriverMessage where
DriverInstantiationNodeInDependencyGeneration {}
-> ErrorWithoutFlag
DriverNoConfiguredLLVMToolchain
- -> ErrorWithoutFlag
+ -> WarningWithoutFlag
diagnosticHints = \case
DriverUnknownMessage m
=====================================
compiler/GHC/Tc/Solver/Equality.hs
=====================================
@@ -193,12 +193,8 @@ zonkEqTypes ev eq_rel ty1 ty2
then tycon tc1 tys1 tys2
else bale_out ty1 ty2
- go ty1 ty2
- | Just (ty1a, ty1b) <- tcSplitAppTyNoView_maybe ty1
- , Just (ty2a, ty2b) <- tcSplitAppTyNoView_maybe ty2
- = do { res_a <- go ty1a ty2a
- ; res_b <- go ty1b ty2b
- ; return $ combine_rev mkAppTy res_b res_a }
+ -- If you are temppted to add a case for AppTy/AppTy, be careful
+ -- See Note [zonkEqTypes and the PKTI]
go ty1@(LitTy lit1) (LitTy lit2)
| lit1 == lit2
@@ -274,6 +270,32 @@ zonkEqTypes ev eq_rel ty1 ty2
combine_rev f (Right tys) (Right ty) = Right (f ty tys)
+{- Note [zonkEqTypes and the PKTI]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Because `zonkEqTypes` does /partial/ zonking, we need to be very careful
+to maintain the Purely Kinded Type Invariant: see GHC.Tc.Gen/HsType
+HsNote [The Purely Kinded Type Invariant (PKTI)].
+
+In #26256 we try to solve this equality constraint:
+ Int :-> Maybe Char ~# k0 Int (m0 Char)
+where m0 and k0 are unification variables, and
+ m0 :: Type -> Type
+It happens that m0 was already unified
+ m0 := (w0 :: kappa)
+where kappa is another unification variable that is also already unified:
+ kappa := Type->Type.
+So the original type satisifed the PKTI, but a partially-zonked form
+ k0 Int (w0 Char)
+does not!! (This a bit reminiscent of Note [mkAppTyM].)
+
+The solution I have adopted is simply to make `zonkEqTypes` bale out on `AppTy`.
+After all, it's only supposed to be a quick hack to see if two types are already
+equal; if we bale out we'll just get into the "proper" canonicaliser.
+
+The only tricky thing about this approach is that it relies on /omitting/
+code -- for the AppTy/AppTy case! Hence this Note
+-}
+
{- *********************************************************************
* *
* canonicaliseEquality
=====================================
configure.ac
=====================================
@@ -351,15 +351,23 @@ fi
dnl ** Building a cross compiler?
dnl --------------------------------------------------------------
-CrossCompiling=NO
-# If 'host' and 'target' differ, then this means we are building a cross-compiler.
-if test "$target" != "$host" ; then
- CrossCompiling=YES
- cross_compiling=yes # This tells configure that it can accept just 'target',
- # otherwise you get
- # configure: error: cannot run C compiled programs.
- # If you meant to cross compile, use `--host'.
+dnl We allow the user to override this since the target/host check
+dnl can get this wrong in some particular cases. See #26236.
+if test -z "$CrossCompiling" ; then
+ CrossCompiling=NO
+ # If 'host' and 'target' differ, then this means we are building a cross-compiler.
+ if test "$target" != "$host" ; then
+ CrossCompiling=YES
+ fi
+fi
+if test "$CrossCompiling" = "YES"; then
+ # This tells configure that it can accept just 'target',
+ # otherwise you get
+ # configure: error: cannot run C compiled programs.
+ # If you meant to cross compile, use `--host'.
+ cross_compiling=yes
fi
+
if test "$BuildPlatform" != "$HostPlatform" ; then
AC_MSG_ERROR([
You've selected:
=====================================
libraries/base/changelog.md
=====================================
@@ -1,5 +1,8 @@
# Changelog for [`base` package](http://hackage.haskell.org/package/base)
+## 4.21.2.0 *Sept 2024*
+ * Fix bug where `naturalAndNot` was incorrectly truncating results ([CLC proposal #350](github.com/haskell/core-libraries-committee/issues/350))
+
## 4.21.1.0 *Sept 2024*
* Fix incorrect results of `integerPowMod` when the base is 0 and the exponent is negative, and `integerRecipMod` when the modulus is zero ([#26017](https://gitlab.haskell.org/ghc/ghc/-/issues/26017)).
=====================================
libraries/ghc-bignum/changelog.md
=====================================
@@ -4,6 +4,7 @@
- Expose backendName
- Add `naturalSetBit[#]` (#21173), `naturalClearBit[#]` (#21175), `naturalComplementBit[#]` (#21181)
+- Fix bug where `naturalAndNot` was incorrectly truncating results (#26230)
## 1.2
=====================================
libraries/ghc-bignum/src/GHC/Num/Natural.hs
=====================================
@@ -488,7 +488,7 @@ naturalAndNot :: Natural -> Natural -> Natural
{-# NOINLINE naturalAndNot #-}
naturalAndNot (NS n) (NS m) = NS (n `and#` not# m)
naturalAndNot (NS n) (NB m) = NS (n `and#` not# (bigNatToWord# m))
-naturalAndNot (NB n) (NS m) = NS (bigNatToWord# n `and#` not# m)
+naturalAndNot (NB n) (NS m) = NB (bigNatAndNotWord# n m)
naturalAndNot (NB n) (NB m) = naturalFromBigNat# (bigNatAndNot n m)
naturalOr :: Natural -> Natural -> Natural
=====================================
rts/Messages.c
=====================================
@@ -180,13 +180,22 @@ uint32_t messageBlackHole(Capability *cap, MessageBlackHole *msg)
bh_info != &stg_CAF_BLACKHOLE_info &&
bh_info != &__stg_EAGER_BLACKHOLE_info &&
bh_info != &stg_WHITEHOLE_info) {
- // if it is a WHITEHOLE, then a thread is in the process of
- // trying to BLACKHOLE it. But we know that it was once a
- // BLACKHOLE, so there is at least a valid pointer in the
- // payload, so we can carry on.
return 0;
}
+ // If we see a WHITEHOLE then we should wait for it to turn into a BLACKHOLE.
+ // Otherwise we might look at the indirectee and segfault.
+ // See "Exception handling" in Note [Thunks, blackholes, and indirections]
+ // We might be looking at a *fresh* THUNK being WHITEHOLE-d so we can't
+ // guarantee that the indirectee is a valid pointer.
+#if defined(THREADED_RTS)
+ if (bh_info == &stg_WHITEHOLE_info) {
+ while(ACQUIRE_LOAD(&bh->header.info) == &stg_WHITEHOLE_info) {
+ busy_wait_nop();
+ }
+ }
+#endif
+
// The blackhole must indirect to a TSO, a BLOCKING_QUEUE, an IND,
// or a value.
StgClosure *p;
=====================================
rts/StgMiscClosures.cmm
=====================================
@@ -31,6 +31,7 @@ import CLOSURE ENT_VIA_NODE_ctr;
import CLOSURE RtsFlags;
import CLOSURE stg_BLOCKING_QUEUE_CLEAN_info;
import CLOSURE stg_BLOCKING_QUEUE_DIRTY_info;
+import CLOSURE stg_END_TSO_QUEUE_closure;
import CLOSURE stg_IND_info;
import CLOSURE stg_MSG_BLACKHOLE_info;
import CLOSURE stg_TSO_info;
@@ -574,6 +575,9 @@ retry:
MessageBlackHole_tso(msg) = CurrentTSO;
MessageBlackHole_bh(msg) = node;
+ // Ensure that the link field is a valid closure,
+ // since we might turn this into an indirection in wakeBlockingQueue()
+ MessageBlackHole_link(msg) = stg_END_TSO_QUEUE_closure;
SET_HDR(msg, stg_MSG_BLACKHOLE_info, CCS_SYSTEM);
// messageBlackHole has appropriate memory barriers when this object is exposed.
// See Note [Heap memory barriers].
=====================================
rts/Updates.h
=====================================
@@ -333,6 +333,10 @@
* `AP_STACK` closure recording the aborted execution state.
* See `RaiseAsync.c:raiseAsync` for details.
*
+ * This can combine with indirection shortcutting during GC to replace a BLACKHOLE
+ * with a fresh THUNK. We should be very careful here since the THUNK will have an
+ * undefined value in the indirectee field. Looking at the indirectee field can then
+ * lead to a segfault such as #26205.
*
* CAFs
* ----
=====================================
testsuite/tests/cpranal/sigs/T25944.hs
=====================================
@@ -0,0 +1,114 @@
+{-# LANGUAGE UndecidableInstances, LambdaCase #-}
+
+-- | This file starts with a small reproducer for #25944 that is easy to debug
+-- and then continues with a much larger MWE that is faithful to the original
+-- issue.
+module T25944 (foo, bar, popMinOneT, popMinOne) where
+
+import Data.Functor.Identity ( Identity(..) )
+import Data.Coerce
+
+data ListCons a b = Nil | a :- !b
+newtype Fix f = Fix (f (Fix f)) -- Rec
+
+foo :: Fix (ListCons a) -> Fix (ListCons a) -> Fix (ListCons a)
+foo a b = go a
+ where
+ -- The outer loop arranges it so that the base case `go as` of `go2` is
+ -- bottom on the first iteration of the loop.
+ go (Fix Nil) = Fix Nil
+ go (Fix (a :- as)) = Fix (a :- go2 b)
+ where
+ go2 (Fix Nil) = go as
+ go2 (Fix (b :- bs)) = Fix (b :- go2 bs)
+
+bar :: Int -> (Fix (ListCons Int), Int)
+bar n = (foo (Fix Nil) (Fix Nil), n) -- should still have CPR property
+
+-- Now the actual reproducer from #25944:
+
+newtype ListT m a = ListT { runListT :: m (ListCons a (ListT m a)) }
+
+cons :: Applicative m => a -> ListT m a -> ListT m a
+cons x xs = ListT (pure (x :- xs))
+
+nil :: Applicative m => ListT m a
+nil = ListT (pure Nil)
+
+instance Functor m => Functor (ListT m) where
+ fmap f (ListT m) = ListT (go <$> m)
+ where
+ go Nil = Nil
+ go (a :- m) = f a :- (f <$> m)
+
+foldListT :: ((ListCons a (ListT m a) -> c) -> m (ListCons a (ListT m a)) -> b)
+ -> (a -> b -> c)
+ -> c
+ -> ListT m a -> b
+foldListT r c n = r h . runListT
+ where
+ h Nil = n
+ h (x :- ListT xs) = c x (r h xs)
+{-# INLINE foldListT #-}
+
+mapListT :: forall a m b. Monad m => (a -> ListT m b -> ListT m b) -> ListT m b -> ListT m a -> ListT m b
+mapListT =
+ foldListT
+ ((coerce ::
+ ((ListCons a (ListT m a) -> m (ListCons b (ListT m b))) -> m (ListCons a (ListT m a)) -> m (ListCons b (ListT m b))) ->
+ ((ListCons a (ListT m a) -> ListT m b) -> m (ListCons a (ListT m a)) -> ListT m b))
+ (=<<))
+{-# INLINE mapListT #-}
+
+instance Monad m => Applicative (ListT m) where
+ pure x = cons x nil
+ {-# INLINE pure #-}
+ liftA2 f xs ys = mapListT (\x zs -> mapListT (cons . f x) zs ys) nil xs
+ {-# INLINE liftA2 #-}
+
+instance Monad m => Monad (ListT m) where
+ xs >>= f = mapListT (flip (mapListT cons) . f) nil xs
+ {-# INLINE (>>=) #-}
+
+infixr 5 :<
+data Node w a b = Leaf a | !w :< b
+ deriving (Functor)
+
+bimapNode f g (Leaf x) = Leaf (f x)
+bimapNode f g (x :< xs) = x :< g xs
+
+newtype HeapT w m a = HeapT { runHeapT :: ListT m (Node w a (HeapT w m a)) }
+
+-- | The 'Heap' type, specialised to the 'Identity' monad.
+type Heap w = HeapT w Identity
+
+instance Functor m => Functor (HeapT w m) where
+ fmap f = HeapT . fmap (bimapNode f (fmap f)) . runHeapT
+
+instance Monad m => Applicative (HeapT w m) where
+ pure = HeapT . pure . Leaf
+ (<*>) = liftA2 id
+
+instance Monad m => Monad (HeapT w m) where
+ HeapT m >>= f = HeapT (m >>= g)
+ where
+ g (Leaf x) = runHeapT (f x)
+ g (w :< xs) = pure (w :< (xs >>= f))
+
+popMinOneT :: forall w m a. (Monoid w, Monad m) => HeapT w m a -> m (Maybe ((a, w), HeapT w m a))
+popMinOneT = go mempty [] . runHeapT
+ where
+ go' :: w -> Maybe (w, HeapT w m a) -> m (Maybe ((a, w), HeapT w m a))
+ go' a Nothing = pure Nothing
+ go' a (Just (w, HeapT xs)) = go (a <> w) [] xs
+
+ go :: w -> [(w, HeapT w m a)] -> ListT m (Node w a (HeapT w m a)) -> m (Maybe ((a, w), HeapT w m a))
+ go w a (ListT xs) = xs >>= \case
+ Nil -> go' w (undefined)
+ Leaf x :- xs -> pure (Just ((x, w), undefined >> HeapT (foldl (\ys (yw,y) -> ListT (pure ((yw :< y) :- ys))) xs a)))
+ (u :< x) :- xs -> go w ((u,x) : a) xs
+{-# INLINE popMinOneT #-}
+
+popMinOne :: Monoid w => Heap w a -> Maybe ((a, w), Heap w a)
+popMinOne = runIdentity . popMinOneT
+{-# INLINE popMinOne #-}
=====================================
testsuite/tests/cpranal/sigs/T25944.stderr
=====================================
@@ -0,0 +1,17 @@
+
+==================== Cpr signatures ====================
+T25944.$fApplicativeHeapT:
+T25944.$fApplicativeListT:
+T25944.$fFunctorHeapT:
+T25944.$fFunctorListT:
+T25944.$fFunctorNode:
+T25944.$fMonadHeapT:
+T25944.$fMonadListT:
+T25944.bar: 1
+T25944.foo:
+T25944.popMinOne: 2(1(1,))
+T25944.popMinOneT:
+T25944.runHeapT:
+T25944.runListT:
+
+
=====================================
testsuite/tests/cpranal/sigs/all.T
=====================================
@@ -12,3 +12,4 @@ test('T16040', normal, compile, [''])
test('T19232', normal, compile, [''])
test('T19398', normal, compile, [''])
test('T19822', normal, compile, [''])
+test('T25944', normal, compile, [''])
=====================================
testsuite/tests/numeric/should_run/T26230.hs
=====================================
@@ -0,0 +1,8 @@
+import Data.Bits
+import GHC.Num.Natural
+
+main = do
+ print $ naturalAndNot ((2 ^ 4) .|. (2 ^ 3)) (2 ^ 3)
+ print $ naturalAndNot ((2 ^ 129) .|. (2 ^ 65)) (2 ^ 65)
+ print $ naturalAndNot ((2 ^ 4) .|. (2 ^ 3)) ((2 ^ 65) .|. (2 ^ 3))
+ print $ naturalAndNot ((2 ^ 65) .|. (2 ^ 3)) (2 ^ 3)
=====================================
testsuite/tests/numeric/should_run/T26230.stdout
=====================================
@@ -0,0 +1,4 @@
+16
+680564733841876926926749214863536422912
+16
+36893488147419103232
=====================================
testsuite/tests/numeric/should_run/all.T
=====================================
@@ -87,3 +87,4 @@ test('T24066', normal, compile_and_run, [''])
test('div01', normal, compile_and_run, [''])
test('T24245', normal, compile_and_run, [''])
test('T25653', normal, compile_and_run, [''])
+test('T26230', normal, compile_and_run, [''])
=====================================
testsuite/tests/partial-sigs/should_compile/T26256.hs
=====================================
@@ -0,0 +1,23 @@
+{-# LANGUAGE GHC2021 #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE PartialTypeSignatures #-}
+
+module M (go) where
+
+import Data.Kind
+
+type Apply :: (Type -> Type) -> Type
+data Apply m
+
+type (:->) :: Type -> Type -> Type
+type family (:->) where (:->) = (->)
+
+f :: forall (k :: Type -> Type -> Type) (m :: Type -> Type).
+ k Int (m Char) -> k Bool (Apply m)
+f = f
+
+x :: Int :-> Maybe Char
+x = x
+
+go :: Bool -> _ _
+go = f x
=====================================
testsuite/tests/partial-sigs/should_compile/T26256.stderr
=====================================
@@ -0,0 +1,8 @@
+T26256.hs:22:15: warning: [GHC-88464] [-Wpartial-type-signatures (in -Wdefault)]
+ • Found type wildcard ‘_’ standing for ‘Apply :: (* -> *) -> *’
+ • In the type signature: go :: Bool -> _ _
+
+T26256.hs:22:17: warning: [GHC-88464] [-Wpartial-type-signatures (in -Wdefault)]
+ • Found type wildcard ‘_’ standing for ‘Maybe :: * -> *’
+ • In the first argument of ‘_’, namely ‘_’
+ In the type signature: go :: Bool -> _ _
=====================================
testsuite/tests/partial-sigs/should_compile/all.T
=====================================
@@ -108,3 +108,4 @@ test('T21667', normal, compile, [''])
test('T22065', normal, compile, [''])
test('T16152', normal, compile, [''])
test('T20076', expect_broken(20076), compile, [''])
+test('T26256', normal, compile, [''])
=====================================
testsuite/tests/typecheck/should_compile/T26256a.hs
=====================================
@@ -0,0 +1,19 @@
+{-# LANGUAGE GHC2021 #-}
+{-# LANGUAGE TypeFamilies #-}
+
+module T26256 (go) where
+
+import Data.Kind
+
+class Cat k where (<<<) :: k a b -> k x a -> k x b
+instance Cat (->) where (<<<) = (.)
+class Pro k p where pro :: k a b s t -> p a b -> p s t
+data Hiding o a b s t = forall e. Hiding (s -> o e a)
+newtype Apply e a = Apply (e a)
+
+type (:->) :: Type -> Type -> Type
+type family (:->) where
+ (:->) = (->)
+
+go :: (Pro (Hiding Apply) p) => (s :-> e a) -> p a b -> p s t
+go sea = pro (Hiding (Apply <<< sea))
=====================================
testsuite/tests/typecheck/should_compile/all.T
=====================================
@@ -935,3 +935,4 @@ test('T24845a', normal, compile, [''])
test('T23501a', normal, compile, [''])
test('T23501b', normal, compile, [''])
test('T25597', normal, compile, [''])
+test('T26256a', normal, compile, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/75d546fe58d4532b4f39814c453928…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/75d546fe58d4532b4f39814c453928…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 10 commits: RTS: rely less on Hadrian for flag setting (#25843)
by Marge Bot (@marge-bot) 02 Sep '25
by Marge Bot (@marge-bot) 02 Sep '25
02 Sep '25
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
a1567efd by Sylvain Henry at 2025-09-01T23:01:35-04:00
RTS: rely less on Hadrian for flag setting (#25843)
Hadrian used to pass -Dfoo command-line flags directly to build the rts.
We can replace most of these flags with CPP based on cabal flags.
It makes building boot libraries with cabal-install simpler (cf #25843).
- - - - -
ca5b0283 by Sergey Vinokurov at 2025-09-01T23:02:23-04:00
Remove unnecessary irrefutable patterns from Bifunctor instances for tuples
Implementation of https://github.com/haskell/core-libraries-committee/issues/339
Metric Decrease:
mhu-perf
- - - - -
2da84b7a by sheaf at 2025-09-01T23:03:23-04:00
Only use active rules when simplifying rule RHSs
When we are simplifying the RHS of a rule, we make sure to only apply
rewrites from rules that are active throughout the original rule's
range of active phases.
For example, if a rule is always active, we only fire rules that are
themselves always active when simplifying the RHS. Ditto for inline
activations.
This is achieved by setting the simplifier phase to a range of phases,
using the new SimplPhaseRange constructor. Then:
1. When simplifying the RHS of a rule, or of a stable unfolding,
we set the simplifier phase to a range of phases, computed from
the activation of the RULE/unfolding activation, using the
function 'phaseFromActivation'.
The details are explained in Note [What is active in the RHS of a RULE?]
in GHC.Core.Opt.Simplify.Utils.
2. The activation check for other rules and inlinings is then:
does the activation of the other rule/inlining cover the whole
phase range set in sm_phase? This continues to use the 'isActive'
function, which now accounts for phase ranges.
On the way, this commit also moves the exact-print SourceText annotation
from the Activation datatype to the ActivationAnn type. This keeps the
main Activation datatype free of any extra cruft.
Fixes #26323
- - - - -
f3f31d39 by Rodrigo Mesquita at 2025-09-02T07:19:34-04:00
cleanup: Move dehydrateCgBreakInfo to Stg2Bc
This no longer has anything to do with Core.
- - - - -
e617dedd by Rodrigo Mesquita at 2025-09-02T07:19:34-04:00
rts/Disassembler: Fix spacing of BRK_FUN
- - - - -
677289dd by Rodrigo Mesquita at 2025-09-02T07:19:35-04:00
debugger: Fix bciPtr in Step-out
We need to use `BCO_NEXT` to move bciPtr to ix=1, because ix=0 points to
the instruction itself!
I do not understand how this didn't crash before.
- - - - -
5df7beee by Rodrigo Mesquita at 2025-09-02T07:19:35-04:00
debugger: Allow BRK_FUNs to head case continuation BCOs
When we start executing a BCO, we may want to yield to the scheduler:
this may be triggered by a heap/stack check, context switch, or a
breakpoint. To yield, we need to put the stack in a state such that
when execution is resumed we are back to where we yielded from.
Previously, a BKR_FUN could only head a function BCO because we only
knew how to construct a valid stack for yielding from one -- simply add
`apply_interp_info` + the BCO to resume executing. This is valid because
the stack at the start of run_BCO is headed by that BCO's arguments.
However, in case continuation BCOs (as per Note [Case continuation BCOs]),
we couldn't easily reconstruct a valid stack that could be resumed
because we dropped too soon the stack frames regarding the value
returned (stg_ret) and received (stg_ctoi) by that continuation.
This is especially tricky because of the variable type and size return
frames (e.g. pointer ret_p/ctoi_R1p vs a tuple ret_t/ctoi_t2).
The trick to being able to yield from a BRK_FUN at the start of a case
cont BCO is to stop removing the ret frame headers eagerly and instead
keep them until the BCO starts executing. The new layout at the start of
a case cont. BCO is described by the new Note [Stack layout when entering run_BCO].
Now, we keep the ret_* and ctoi_* frames when entering run_BCO.
A BRK_FUN is then executed if found, and the stack is yielded as-is with
the preserved ret and ctoi frames.
Then, a case cont BCO's instructions always SLIDE off the headers of the
ret and ctoi frames, in StgToByteCode.doCase, turning a stack like
| .... |
+---------------+
| fv2 |
+---------------+
| fv1 |
+---------------+
| BCO |
+---------------+
| stg_ctoi_ret_ |
+---------------+
| retval |
+---------------+
| stg_ret_..... |
+---------------+
into
| .... |
+---------------+
| fv2 |
+---------------+
| fv1 |
+---------------+
| retval |
+---------------+
for the remainder of the BCO.
Moreover, this more uniform approach of keeping the ret and ctoi frames
means we need less ad-hoc logic concerning the variable size of
ret_tuple vs ret_p/np frames in the code generator and interpreter:
Always keep the return to cont. stack intact at the start of run_BCO,
and the statically generated instructions will take care of adjusting
it.
Unlocks BRK_FUNs at the start of case cont. BCOs which will enable a
better user-facing step-out (#26042) which is free of the bugs the
current BRK_ALTS implementation suffers from (namely, using BRK_FUN
rather than BRK_ALTS in a case cont. means we'll never accidentally end
up in a breakpoint "deeper" than the continuation, because we stop at
the case cont itself rather than on the first breakpoint we evaluate
after it).
- - - - -
d161188f by Rodrigo Mesquita at 2025-09-02T07:19:35-04:00
BRK_FUN with InternalBreakLocs for code-generation time breakpoints
At the start of a case continuation BCO, place a BRK_FUN.
This BRK_FUN uses the new "internal breakpoint location" -- allowing us
to come up with a valid source location for this breakpoint that is not associated with a source-level tick.
For case continuation BCOs, we use the last tick seen before it as the
source location. The reasoning is described in Note [Debugger: Stepout internal break locs].
Note how T26042c, which was broken because it displayed the incorrect
behavior of the previous step out when we'd end up at a deeper level
than the one from which we initiated step-out, is now fixed.
As of this commit, BRK_ALTS is now dead code and is thus dropped.
Note [Debugger: Stepout internal break locs]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Step-out tells the interpreter to run until the current function
returns to where it was called from, and stop there.
This is achieved by enabling the BRK_FUN found on the first RET_BCO
frame on the stack (See [Note Debugger: Step-out]).
Case continuation BCOs (which select an alternative branch) must
therefore be headed by a BRK_FUN. An example:
f x = case g x of <--- end up here
1 -> ...
2 -> ...
g y = ... <--- step out from here
- `g` will return a value to the case continuation BCO in `f`
- The case continuation BCO will receive the value returned from g
- Match on it and push the alternative continuation for that branch
- And then enter that alternative.
If we step-out of `g`, the first RET_BCO on the stack is the case
continuation of `f` -- execution should stop at its start, before
selecting an alternative. (One might ask, "why not enable the breakpoint
in the alternative instead?", because the alternative continuation is
only pushed to the stack *after* it is selected by the case cont. BCO)
However, the case cont. BCO is not associated with any source-level
tick, it is merely the glue code which selects alternatives which do
have source level ticks. Therefore, we have to come up at code
generation time with a breakpoint location ('InternalBreakLoc') to
display to the user when it is stopped there.
Our solution is to use the last tick seen just before reaching the case
continuation. This is robust because a case continuation will thus
always have a relevant breakpoint location:
- The source location will be the last source-relevant expression
executed before the continuation is pushed
- So the source location will point to the thing you've just stepped
out of
- Doing :step-local from there will put you on the selected
alternative (which at the source level may also be the e.g. next
line in a do-block)
Examples, using angle brackets (<<...>>) to denote the breakpoint span:
f x = case <<g x>> {- step in here -} of
1 -> ...
2 -> ...>
g y = <<...>> <--- step out from here
...
f x = <<case g x of <--- end up here, whole case highlighted
1 -> ...
2 -> ...>>
doing :step-local ...
f x = case g x of
1 -> <<...>> <--- stop in the alternative
2 -> ...
A second example based on T26042d2, where the source is a do-block IO
action, optimised to a chain of `case expressions`.
main = do
putStrLn "hello1"
<<f>> <--- step-in here
putStrLn "hello3"
putStrLn "hello4"
f = do
<<putStrLn "hello2.1">> <--- step-out from here
putStrLn "hello2.2"
...
main = do
putStrLn "hello1"
<<f>> <--- end up here again, the previously executed expression
putStrLn "hello3"
putStrLn "hello4"
doing step/step-local ...
main = do
putStrLn "hello1"
f
<<putStrLn "hello3">> <--- straight to the next line
putStrLn "hello4"
Finishes #26042
- - - - -
65eda493 by Rodrigo Mesquita at 2025-09-02T07:19:35-04:00
debugger: Re-use the last BreakpointId whole in step-out
Previously, to come up with a location to stop at for `:stepout`, we
would store the location of the last BreakpointId surrounding the
continuation, as described by Note [Debugger: Stepout internal break locs].
However, re-using just the location from the last source breakpoint
isn't sufficient to provide the necessary information in the break
location. Specifically, it wouldn't bind any variables at that location.
Really, there is no reason not to re-use the last breakpoint wholesale,
and re-use all the information we had there. Step-out should behave just
as if we had stopped at the call, but s.t. continuing will not
re-execute the call.
This commit updates the CgBreakInfo to always store a BreakpointId, be
it the original one or the one we're emulating (for step-out).
It makes variable bindings on :stepout work
- - - - -
6f6fe6d1 by sheaf at 2025-09-02T07:19:38-04:00
Revert accidental changes to hie.yaml
- - - - -
62 changed files:
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Breakpoints.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/Core/Opt/Pipeline/Types.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Parser.y
- compiler/GHC/Runtime/Debugger/Breakpoints.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Utils/Binary.hs
- ghc/GHCi/UI.hs
- hadrian/src/Settings/Packages.hs
- libraries/base/changelog.md
- libraries/base/src/Data/Bifunctor.hs
- libraries/ghci/GHCi/Run.hs
- rts/Disassembler.c
- rts/Interpreter.c
- rts/Profiling.c
- rts/RtsMessages.c
- rts/RtsUtils.c
- rts/Trace.c
- rts/include/rts/Bytecodes.h
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/ghci.debugger/scripts/T26042b.script
- testsuite/tests/ghci.debugger/scripts/T26042b.stdout
- testsuite/tests/ghci.debugger/scripts/T26042c.script
- testsuite/tests/ghci.debugger/scripts/T26042c.stdout
- + testsuite/tests/ghci.debugger/scripts/T26042d2.hs
- + testsuite/tests/ghci.debugger/scripts/T26042d2.script
- + testsuite/tests/ghci.debugger/scripts/T26042d2.stdout
- testsuite/tests/ghci.debugger/scripts/T26042e.stdout
- testsuite/tests/ghci.debugger/scripts/T26042f.script
- testsuite/tests/ghci.debugger/scripts/T26042f1.stdout
- testsuite/tests/ghci.debugger/scripts/T26042f2.stdout
- testsuite/tests/ghci.debugger/scripts/T26042g.stdout
- testsuite/tests/ghci.debugger/scripts/all.T
- testsuite/tests/perf/compiler/T4007.stdout
- testsuite/tests/simplCore/should_compile/T15056.stderr
- testsuite/tests/simplCore/should_compile/T15445.stderr
- + testsuite/tests/simplCore/should_compile/T26323b.hs
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T26323.hs
- + testsuite/tests/simplCore/should_run/T26323.stdout
- testsuite/tests/simplCore/should_run/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/295be6d4dbbd0881e97b8057909b2e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/295be6d4dbbd0881e97b8057909b2e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
sheaf pushed new branch wip/hie-yaml at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/hie-yaml
You're receiving this email because of your account on gitlab.haskell.org.
1
0
02 Sep '25
Simon Peyton Jones pushed to branch wip/T26315 at Glasgow Haskell Compiler / GHC
Commits:
4b903d4d by Simon Peyton Jones at 2025-09-02T08:30:11+01:00
Fix unused variables
- - - - -
1 changed file:
- compiler/GHC/Tc/Solver/Dict.hs
Changes:
=====================================
compiler/GHC/Tc/Solver/Dict.hs
=====================================
@@ -767,11 +767,10 @@ and Given/instance fundeps entirely.
tryInertDicts :: DictCt -> SolverStage ()
tryInertDicts dict_ct
= Stage $ do { inerts <- getInertCans
- ; mode <- getTcSMode
- ; try_inert_dicts mode inerts dict_ct }
+ ; try_inert_dicts inerts dict_ct }
-try_inert_dicts :: TcSMode -> InertCans -> DictCt -> TcS (StopOrContinue ())
-try_inert_dicts mode inerts dict_w@(DictCt { di_ev = ev_w, di_cls = cls, di_tys = tys })
+try_inert_dicts :: InertCans -> DictCt -> TcS (StopOrContinue ())
+try_inert_dicts inerts dict_w@(DictCt { di_ev = ev_w, di_cls = cls, di_tys = tys })
| Just dict_i <- lookupInertDict inerts cls tys
, let ev_i = dictCtEvidence dict_i
loc_i = ctEvLoc ev_i
@@ -866,8 +865,7 @@ try_instances inerts work_item@(DictCt { di_ev = ev, di_cls = cls
| otherwise -- Wanted, but not cached
= do { dflags <- getDynFlags
- ; mode <- getTcSMode
- ; lkup_res <- matchClassInst dflags mode inerts cls xis dict_loc
+ ; lkup_res <- matchClassInst dflags inerts cls xis dict_loc
; case lkup_res of
OneInst { cir_what = what }
-> do { let is_local_given = case what of { LocalInstance -> True; _ -> False }
@@ -925,10 +923,10 @@ checkInstanceOK loc what pred
| otherwise
= loc
-matchClassInst :: DynFlags -> TcSMode -> InertSet
+matchClassInst :: DynFlags -> InertSet
-> Class -> [Type]
-> CtLoc -> TcS ClsInstResult
-matchClassInst dflags mode inerts clas tys loc
+matchClassInst dflags inerts clas tys loc
-- First check whether there is an in-scope Given that could
-- match this constraint. In that case, do not use any instance
-- whether top level, or local quantified constraints.
@@ -939,7 +937,7 @@ matchClassInst dflags mode inerts clas tys loc
-- It is always safe to unpack constraint tuples
-- And if we don't do so, we may never solve it at all
-- See Note [Solving tuple constraints]
- , not (noMatchableGivenDicts mode inerts loc clas tys)
+ , not (noMatchableGivenDicts inerts loc clas tys)
= do { traceTcS "Delaying instance application" $
vcat [ text "Work item:" <+> pprClassPred clas tys ]
; return NotSure }
@@ -970,8 +968,8 @@ matchClassInst dflags mode inerts clas tys loc
-- potentially, match the given class constraint. This is used when checking to see if a
-- Given might overlap with an instance. See Note [Instance and Given overlap]
-- in GHC.Tc.Solver.Dict
-noMatchableGivenDicts :: TcSMode -> InertSet -> CtLoc -> Class -> [TcType] -> Bool
-noMatchableGivenDicts mode inerts@(IS { inert_cans = inert_cans }) loc_w clas tys
+noMatchableGivenDicts :: InertSet -> CtLoc -> Class -> [TcType] -> Bool
+noMatchableGivenDicts inerts@(IS { inert_cans = inert_cans }) loc_w clas tys
= not $ anyBag matchable_given $
findDictsByClass (inert_dicts inert_cans) clas
where
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4b903d4d1e4a9d95264339305661a29…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4b903d4d1e4a9d95264339305661a29…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Only use active rules when simplifying rule RHSs
by Marge Bot (@marge-bot) 02 Sep '25
by Marge Bot (@marge-bot) 02 Sep '25
02 Sep '25
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
2da84b7a by sheaf at 2025-09-01T23:03:23-04:00
Only use active rules when simplifying rule RHSs
When we are simplifying the RHS of a rule, we make sure to only apply
rewrites from rules that are active throughout the original rule's
range of active phases.
For example, if a rule is always active, we only fire rules that are
themselves always active when simplifying the RHS. Ditto for inline
activations.
This is achieved by setting the simplifier phase to a range of phases,
using the new SimplPhaseRange constructor. Then:
1. When simplifying the RHS of a rule, or of a stable unfolding,
we set the simplifier phase to a range of phases, computed from
the activation of the RULE/unfolding activation, using the
function 'phaseFromActivation'.
The details are explained in Note [What is active in the RHS of a RULE?]
in GHC.Core.Opt.Simplify.Utils.
2. The activation check for other rules and inlinings is then:
does the activation of the other rule/inlining cover the whole
phase range set in sm_phase? This continues to use the 'isActive'
function, which now accounts for phase ranges.
On the way, this commit also moves the exact-print SourceText annotation
from the Activation datatype to the ActivationAnn type. This keeps the
main Activation datatype free of any extra cruft.
Fixes #26323
- - - - -
28 changed files:
- compiler/GHC/Core/Opt/Pipeline/Types.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Parser.y
- compiler/GHC/Tc/Deriv/Generics.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Utils/Binary.hs
- hie.yaml
- testsuite/tests/perf/compiler/T4007.stdout
- testsuite/tests/simplCore/should_compile/T15056.stderr
- testsuite/tests/simplCore/should_compile/T15445.stderr
- + testsuite/tests/simplCore/should_compile/T26323b.hs
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/simplCore/should_run/T26323.hs
- + testsuite/tests/simplCore/should_run/T26323.stdout
- testsuite/tests/simplCore/should_run/all.T
- utils/check-exact/ExactPrint.hs
Changes:
=====================================
compiler/GHC/Core/Opt/Pipeline/Types.hs
=====================================
@@ -10,7 +10,7 @@ import GHC.Core ( CoreProgram )
import GHC.Core.Opt.Monad ( CoreM, FloatOutSwitches )
import GHC.Core.Opt.Simplify ( SimplifyOpts(..) )
-import GHC.Types.Basic ( CompilerPhase(..) )
+import GHC.Types.Basic ( CompilerPhase )
import GHC.Unit.Module.ModGuts
import GHC.Utils.Outputable as Outputable
@@ -52,8 +52,8 @@ data CoreToDo -- These are diff core-to-core passes,
| CoreDoSpecialising
| CoreDoSpecConstr
| CoreCSE
- | CoreDoRuleCheck CompilerPhase String -- Check for non-application of rules
- -- matching this string
+ | CoreDoRuleCheck CompilerPhase String -- Check for non-application of rules
+ -- matching this string
| CoreDoNothing -- Useful when building up
| CoreDoPasses [CoreToDo] -- lists of these things
=====================================
compiler/GHC/Core/Opt/Simplify/Env.hs
=====================================
@@ -12,6 +12,7 @@ module GHC.Core.Opt.Simplify.Env (
-- * Environments
SimplEnv(..), pprSimplEnv, -- Temp not abstract
+ SimplPhase(..), isActive,
seArityOpts, seCaseCase, seCaseFolding, seCaseMerge, seCastSwizzle,
seDoEtaReduction, seEtaExpand, seFloatEnable, seInline, seNames,
seOptCoercionOpts, sePhase, sePlatform, sePreInline,
@@ -145,7 +146,7 @@ here is between "freely set by the caller" and "internally managed by the pass".
Note that it doesn't matter for the decision procedure wheter a value is altered
throughout an iteration of the Simplify pass: The fields sm_phase, sm_inline,
sm_rules, sm_cast_swizzle and sm_eta_expand are updated locally (See the
-definitions of `updModeForStableUnfoldings` and `updModeForRules` in
+definitions of `updModeForStableUnfoldings` and `updModeForRule{LHS,RHS}` in
GHC.Core.Opt.Simplify.Utils) but they are still part of `SimplMode` as the
caller of the Simplify pass needs to provide the initial values for those fields.
@@ -250,7 +251,7 @@ seNames env = sm_names (seMode env)
seOptCoercionOpts :: SimplEnv -> OptCoercionOpts
seOptCoercionOpts env = sm_co_opt_opts (seMode env)
-sePhase :: SimplEnv -> CompilerPhase
+sePhase :: SimplEnv -> SimplPhase
sePhase env = sm_phase (seMode env)
sePlatform :: SimplEnv -> Platform
@@ -270,7 +271,7 @@ seUnfoldingOpts env = sm_uf_opts (seMode env)
-- See Note [The environments of the Simplify pass]
data SimplMode = SimplMode -- See comments in GHC.Core.Opt.Simplify.Monad
- { sm_phase :: !CompilerPhase
+ { sm_phase :: !SimplPhase -- ^ The phase of the simplifier
, sm_names :: ![String] -- ^ Name(s) of the phase
, sm_rules :: !Bool -- ^ Whether RULES are enabled
, sm_inline :: !Bool -- ^ Whether inlining is enabled
@@ -288,13 +289,76 @@ data SimplMode = SimplMode -- See comments in GHC.Core.Opt.Simplify.Monad
, sm_co_opt_opts :: !OptCoercionOpts -- ^ Coercion optimiser options
}
+-- | See Note [SimplPhase]
+data SimplPhase
+ -- | A simplifier phase: InitialPhase, Phase 2, Phase 1, Phase 0, FinalPhase
+ = SimplPhase CompilerPhase
+ -- | Simplifying the RHS of a rule or of a stable unfolding: the range of
+ -- phases of the activation of the rule/stable unfolding.
+ --
+ -- _Invariant:_ 'simplStartPhase' is not a later phase than 'simplEndPhase'.
+ -- Equivalently, 'SimplPhaseRange' is always a non-empty interval of phases.
+ --
+ -- See Note [What is active in the RHS of a RULE?] in GHC.Core.Opt.Simplify.Utils.
+ | SimplPhaseRange
+ { simplStartPhase :: CompilerPhase
+ , simplEndPhase :: CompilerPhase
+ }
+
+ deriving Eq
+
+instance Outputable SimplPhase where
+ ppr (SimplPhase p) = ppr p
+ ppr (SimplPhaseRange s e) = brackets $ ppr s <> text "..." <> ppr e
+
+-- | Is this activation active in this simplifier phase?
+--
+-- For a phase range, @isActive simpl_phase_range act@ is true if and only if
+-- @act@ is active throughout the entire range, as per
+-- Note [What is active in the RHS of a RULE?] in GHC.Core.Opt.Simplify.Utils.
+--
+-- See Note [SimplPhase].
+isActive :: SimplPhase -> Activation -> Bool
+isActive (SimplPhase p) act = isActiveInPhase p act
+isActive (SimplPhaseRange start end) act =
+ -- To check whether the activation is active throughout the whole phase range,
+ -- it's sufficient to check the endpoints of the phase range, because an
+ -- activation can never have gaps (all activations are phase intervals).
+ isActiveInPhase start act && isActiveInPhase end act
+
+{- Note [SimplPhase]
+~~~~~~~~~~~~~~~~~~~~
+In general, the simplifier is invoked in successive phases:
+
+ InitialPhase, Phase 2, Phase 1, Phase 0, FinalPhase
+
+This allows us to control which rules, specialisations and inlinings are
+active at any given point. For example,
+
+ {-# RULE "myRule" [1] lhs = rhs #-}
+
+starts being active in Phase 1, and stays active thereafter. Thus it is active
+in Phase 1, Phase 0, FinalPhase, but not active in InitialPhase or Phase 2.
+
+This simplifier phase is stored in the sm_phase field of SimplMode, usin
+the 'SimplPhase' constructor. This allows us to determine which rules/inlinings
+are active.
+
+When we invoke the simplifier on the RHS of a rule, such as 'rhs' above, instead
+of setting the simplifier mode to a single phase, we use a phase range
+corresponding to the range of phases in which the rule is active, with the
+'SimplPhaseRange' constructor. This allows us to check whether other rules or
+inlinings are active throughout the whole activation of the rule.
+See Note [What is active in the RHS of a RULE?] in GHC.Core.Opt.Simplify.Utils.
+-}
+
instance Outputable SimplMode where
- ppr (SimplMode { sm_phase = p , sm_names = ss
+ ppr (SimplMode { sm_phase = phase , sm_names = ss
, sm_rules = r, sm_inline = i
, sm_cast_swizzle = cs
, sm_eta_expand = eta, sm_case_case = cc })
= text "SimplMode" <+> braces (
- sep [ text "Phase =" <+> ppr p <+>
+ sep [ text "Phase =" <+> ppr phase <+>
brackets (text (concat $ intersperse "," ss)) <> comma
, pp_flag i (text "inline") <> comma
, pp_flag r (text "rules") <> comma
@@ -312,9 +376,8 @@ data FloatEnable -- Controls local let-floating
| FloatNestedOnly -- Local let-floating for nested (NotTopLevel) bindings only
| FloatEnabled -- Do local let-floating on all bindings
-{-
-Note [Local floating]
-~~~~~~~~~~~~~~~~~~~~~
+{- Note [Local floating]
+~~~~~~~~~~~~~~~~~~~~~~~~
The Simplifier can perform local let-floating: it floats let-bindings
out of the RHS of let-bindings. See
Let-floating: moving bindings to give faster programs (ICFP'96)
=====================================
compiler/GHC/Core/Opt/Simplify/Inline.hs
=====================================
@@ -29,7 +29,7 @@ import GHC.Core.FVs( exprFreeIds )
import GHC.Types.Id
import GHC.Types.Var.Env( InScopeSet, lookupInScope )
import GHC.Types.Var.Set
-import GHC.Types.Basic ( Arity, RecFlag(..), isActive )
+import GHC.Types.Basic ( Arity, RecFlag(..) )
import GHC.Utils.Logger
import GHC.Utils.Misc
import GHC.Utils.Outputable
@@ -124,7 +124,7 @@ activeUnfolding mode id
| isCompulsoryUnfolding (realIdUnfolding id)
= True -- Even sm_inline can't override compulsory unfoldings
| otherwise
- = isActive (sm_phase mode) (idInlineActivation id)
+ = isActive (sm_phase mode) (idInlineActivation id)
&& sm_inline mode
-- `or` isStableUnfolding (realIdUnfolding id)
-- Inline things when
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -2458,7 +2458,11 @@ tryInlining env logger var cont
| not (logHasDumpFlag logger Opt_D_verbose_core2core)
= when (isExternalName (idName var)) $
log_inlining $
- sep [text "Inlining done:", nest 4 (ppr var)]
+ sep [text "Inlining done:", nest 4 (ppr var)]
+ -- $$ nest 2 (vcat
+ -- [ text "Simplifier phase:" <+> ppr (sePhase env)
+ -- , text "Unfolding activation:" <+> ppr (idInlineActivation var)
+ -- ])
| otherwise
= log_inlining $
sep [text "Inlining done: " <> ppr var,
@@ -2645,6 +2649,8 @@ tryRules env rules fn args
= log_rule Opt_D_dump_rule_rewrites "Rule fired" $ vcat
[ text "Rule:" <+> ftext (ruleName rule)
, text "Module:" <+> printRuleModule rule
+ --, text "Simplifier phase:" <+> ppr (sePhase env)
+ --, text "Rule activation:" <+> ppr (ruleActivation rule)
, text "Full arity:" <+> ppr (ruleArity rule)
, text "Before:" <+> hang (ppr fn) 2 (sep (map ppr args))
, text "After: " <+> pprCoreExpr rule_rhs ]
@@ -4790,9 +4796,12 @@ simplRules env mb_new_id rules bind_cxt
rhs_cont = case bind_cxt of -- See Note [Rules and unfolding for join points]
BC_Let {} -> mkBoringStop rhs_ty
BC_Join _ cont -> assertPpr join_ok bad_join_msg cont
- lhs_env = updMode updModeForRules env'
- rhs_env = updMode (updModeForStableUnfoldings act) env'
- -- See Note [Simplifying the RHS of a RULE]
+
+ -- See Note [Simplifying rules] and Note [What is active in the RHS of a RULE?]
+ -- in GHC.Core.Opt.Simplify.Utils.
+ lhs_env = updMode updModeForRuleLHS env'
+ rhs_env = updMode (updModeForRuleRHS act) env'
+
-- Force this to avoid retaining reference to old Id
!fn_name' = case mb_new_id of
Just id -> idName id
@@ -4816,12 +4825,3 @@ simplRules env mb_new_id rules bind_cxt
, ru_rhs = occurAnalyseExpr rhs' }) }
-- Remember to occ-analyse, to drop dead code.
-- See Note [OccInfo in unfoldings and rules] in GHC.Core
-
-{- Note [Simplifying the RHS of a RULE]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We can simplify the RHS of a RULE much as we do the RHS of a stable
-unfolding. We used to use the much more conservative updModeForRules
-for the RHS as well as the LHS, but that seems more conservative
-than necesary. Allowing some inlining might, for example, eliminate
-a binding.
--}
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -15,7 +15,7 @@ module GHC.Core.Opt.Simplify.Utils (
preInlineUnconditionally, postInlineUnconditionally,
activeRule,
getUnfoldingInRuleMatch,
- updModeForStableUnfoldings, updModeForRules,
+ updModeForStableUnfoldings, updModeForRuleLHS, updModeForRuleRHS,
-- The BindContext type
BindContext(..), bindContextLevel,
@@ -719,7 +719,7 @@ the LHS.
This is a pretty pathological example, so I'm not losing sleep over
it, but the simplest solution was to check sm_inline; if it is False,
-which it is on the LHS of a rule (see updModeForRules), then don't
+which it is on the LHS of a rule (see updModeForRuleLHS), then don't
make use of the strictness info for the function.
-}
@@ -1069,22 +1069,22 @@ Reason for (b): we want to inline integerCompare here
updModeForStableUnfoldings :: Activation -> SimplMode -> SimplMode
-- See Note [The environments of the Simplify pass]
+-- See Note [Simplifying inside stable unfoldings]
updModeForStableUnfoldings unf_act current_mode
- = current_mode { sm_phase = phaseFromActivation unf_act
- , sm_eta_expand = False
- , sm_inline = True }
- -- sm_eta_expand: see Note [Eta expansion in stable unfoldings and rules]
- -- sm_rules: just inherit; sm_rules might be "off"
- -- because of -fno-enable-rewrite-rules
- where
- phaseFromActivation (ActiveAfter _ n) = Phase n
- phaseFromActivation _ = InitialPhase
+ = current_mode
+ { sm_phase = phaseFromActivation (sm_phase current_mode) unf_act
+ -- See Note [What is active in the RHS of a RULE?]
+ , sm_eta_expand = False
+ -- See Note [Eta expansion in stable unfoldings and rules]
+ , sm_inline = True
+ -- sm_rules: just inherit; sm_rules might be "off" because of -fno-enable-rewrite-rules
+ }
-updModeForRules :: SimplMode -> SimplMode
+updModeForRuleLHS :: SimplMode -> SimplMode
-- See Note [Simplifying rules]
-- See Note [The environments of the Simplify pass]
-updModeForRules current_mode
- = current_mode { sm_phase = InitialPhase
+updModeForRuleLHS current_mode
+ = current_mode { sm_phase = SimplPhase InitialPhase -- doesn't matter
, sm_inline = False
-- See Note [Do not expose strictness if sm_inline=False]
, sm_rules = False
@@ -1092,8 +1092,34 @@ updModeForRules current_mode
-- See Note [Cast swizzling on rule LHSs]
, sm_eta_expand = False }
+updModeForRuleRHS :: Activation -> SimplMode -> SimplMode
+updModeForRuleRHS rule_act current_mode =
+ current_mode
+ -- See Note [What is active in the RHS of a RULE?]
+ { sm_phase = phaseFromActivation (sm_phase current_mode) rule_act
+ , sm_eta_expand = False
+ -- See Note [Eta expansion in stable unfoldings and rules]
+ }
+
+-- | Compute the phase range to set the 'SimplMode' to
+-- when simplifying the RHS of a rule or of a stable unfolding.
+--
+-- See Note [What is active in the RHS of a RULE?]
+phaseFromActivation
+ :: SimplPhase -- ^ the current simplifier phase
+ -> Activation -- ^ the activation of the RULE or stable unfolding
+ -> SimplPhase
+phaseFromActivation p act
+ | isNeverActive act
+ = p
+ | otherwise
+ = SimplPhaseRange act_start act_end
+ where
+ act_start = beginPhase act
+ act_end = endPhase act
+
{- Note [Simplifying rules]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
When simplifying a rule LHS, refrain from /any/ inlining or applying
of other RULES. Doing anything to the LHS is plain confusing, because
it means that what the rule matches is not what the user
@@ -1136,7 +1162,7 @@ where `cv` is a coercion variable. Critically, we really only want
coercion /variables/, not general coercions, on the LHS of a RULE. So
we don't want to swizzle this to
(\x. blah) |> (Refl xty `FunCo` CoVar cv)
-So we switch off cast swizzling in updModeForRules.
+So we switch off cast swizzling in updModeForRuleLHS.
Note [Eta expansion in stable unfoldings and rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1200,6 +1226,62 @@ running it, we don't want to use -O2. Indeed, we don't want to inline
anything, because the byte-code interpreter might get confused about
unboxed tuples and suchlike.
+Note [What is active in the RHS of a RULE?]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Suppose we have either a RULE or an inline pragma with an explicit activation:
+
+ {-# RULE "R" [p] lhs = rhs #-}
+ {-# INLINE [p] foo #-}
+
+We should do some modest rules/inlining stuff in the right-hand sides, partly to
+eliminate senseless crap, and partly to break the recursive knots generated by
+instance declarations. However, we have to be careful about precisely which
+rules/inlinings are active. In particular:
+
+ a) Rules/inlinings that *cease* being active before p should not apply.
+ b) Rules/inlinings that only become active *after* p should also not apply.
+
+In the rest of this Note, we will focus on rules, but everything applies equally
+to the RHSs of stable unfoldings.
+
+Our carefully crafted plan is as follows:
+
+ -------------------------------------------------------------
+ When simplifying the RHS of a RULE R with activation range A,
+ fire only other rules R' that are active throughout all of A.
+ -------------------------------------------------------------
+
+Reason: R might fire in any phase in A. Then R' can fire only if R' is active
+in that phase. If not, it's not safe to unconditionally fire R' in the RHS of R.
+
+This plan is implemented by:
+
+ 1. Setting the simplifier phase to the range of phases
+ corresponding to the start/end phases of the rule's activation.
+ 2. When checking whether another rule is active, we use the function
+ isActive :: SimplPhase -> Activation -> Bool
+ from GHC.Core.Opt.Simplify.Env, which checks whether the other rule is
+ active throughout the whole range of phases.
+
+However, if the rule whose RHS we are simplifying is never active, instead of
+setting the phase range to an empty interval, we keep the current simplifier
+phase. This special case avoids firing ALL rules in the RHS of a never-active
+rule.
+
+You might wonder about a situation such as the following:
+
+ module M1 where
+ {-# RULES "r1" [1] lhs1 = rhs1 #-}
+ {-# RULES "r2" [2] lhs2 = rhs2 #-}
+
+ Current simplifier phase: 1
+
+It looks tempting to use "r1" when simplifying the RHS of "r2", yet we
+**must not** do so: for any module M that imports M1, we are going to start
+simplification in M starting at InitialPhase, and we will see the
+fully simplified rules RHSs imported from M1.
+Conclusion: stick to the plan.
+
Note [Simplifying inside stable unfoldings]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We must take care with simplification inside stable unfoldings (which come from
@@ -1216,33 +1298,9 @@ and thence copied multiple times when g is inlined. HENCE we treat
any occurrence in a stable unfolding as a multiple occurrence, not a single
one; see OccurAnal.addRuleUsage.
-Second, we do want *do* to some modest rules/inlining stuff in stable
-unfoldings, partly to eliminate senseless crap, and partly to break
-the recursive knots generated by instance declarations.
-
-However, suppose we have
- {-# INLINE <act> f #-}
- f = <rhs>
-meaning "inline f in phases p where activation <act>(p) holds".
-Then what inlinings/rules can we apply to the copy of <rhs> captured in
-f's stable unfolding? Our model is that literally <rhs> is substituted for
-f when it is inlined. So our conservative plan (implemented by
-updModeForStableUnfoldings) is this:
-
- -------------------------------------------------------------
- When simplifying the RHS of a stable unfolding, set the phase
- to the phase in which the stable unfolding first becomes active
- -------------------------------------------------------------
-
-That ensures that
-
- a) Rules/inlinings that *cease* being active before p will
- not apply to the stable unfolding, consistent with it being
- inlined in its *original* form in phase p.
-
- b) Rules/inlinings that only become active *after* p will
- not apply to the stable unfolding, again to be consistent with
- inlining the *original* rhs in phase p.
+Second, we must be careful when simplifying the RHS that we do not apply RULES
+which are not active over the whole active range of the stable unfolding.
+This is all explained in Note [What is active in the RHS of a RULE?].
For example,
{-# INLINE f #-}
@@ -1291,8 +1349,7 @@ getUnfoldingInRuleMatch env
= ISE in_scope id_unf
where
in_scope = seInScope env
- phase = sePhase env
- id_unf = whenActiveUnfoldingFun (isActive phase)
+ id_unf = whenActiveUnfoldingFun (isActive (sePhase env))
-- When sm_rules was off we used to test for a /stable/ unfolding,
-- but that seems wrong (#20941)
@@ -1468,7 +1525,8 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
one_occ _ = False
pre_inline_unconditionally = sePreInline env
- active = isActive (sePhase env) (inlinePragmaActivation inline_prag)
+ active = isActive (sePhase env)
+ $ inlinePragmaActivation inline_prag
-- See Note [pre/postInlineUnconditionally in gentle mode]
inline_prag = idInlinePragma bndr
@@ -1505,7 +1563,10 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
-- not ticks. Counting ticks cannot be duplicated, and non-counting
-- ticks around a Lam will disappear anyway.
- early_phase = sePhase env /= FinalPhase
+ early_phase =
+ case sePhase env of
+ SimplPhase p -> p /= FinalPhase
+ SimplPhaseRange _start end -> end /= FinalPhase
-- If we don't have this early_phase test, consider
-- x = length [1,2,3]
-- The full laziness pass carefully floats all the cons cells to
@@ -1516,9 +1577,8 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
--
-- On the other hand, I have seen cases where top-level fusion is
-- lost if we don't inline top level thing (e.g. string constants)
- -- Hence the test for phase zero (which is the phase for all the final
- -- simplifications). Until phase zero we take no special notice of
- -- top level things, but then we become more leery about inlining
+ -- Hence the final phase test: until the final phase, we take no special
+ -- notice of top level things, but then we become more leery about inlining
-- them.
--
-- What exactly to check in `early_phase` above is the subject of #17910.
@@ -1645,8 +1705,7 @@ postInlineUnconditionally env bind_cxt old_bndr bndr rhs
occ_info = idOccInfo old_bndr
unfolding = idUnfolding bndr
uf_opts = seUnfoldingOpts env
- phase = sePhase env
- active = isActive phase (idInlineActivation bndr)
+ active = isActive (sePhase env) $ idInlineActivation bndr
-- See Note [pre/postInlineUnconditionally in gentle mode]
{- Note [Inline small things to avoid creating a thunk]
=====================================
compiler/GHC/Core/Opt/Specialise.hs
=====================================
@@ -19,18 +19,23 @@ import GHC.Core.SimpleOpt( defaultSimpleOpts, simpleOptExprWith, exprIsConApp_ma
import GHC.Core.Predicate
import GHC.Core.Class( classMethods )
import GHC.Core.Coercion( Coercion )
-import GHC.Core.Opt.Monad
+import GHC.Core.DataCon (dataConTyCon)
+
import qualified GHC.Core.Subst as Core
import GHC.Core.Unfold.Make
import GHC.Core
import GHC.Core.Make ( mkLitRubbish )
import GHC.Core.Unify ( tcMatchTy )
import GHC.Core.Rules
+import GHC.Core.Subst (substTickish)
+import GHC.Core.TyCon (tyConClass_maybe)
import GHC.Core.Utils ( exprIsTrivial, exprIsTopLevelBindable
, mkCast, exprType, exprIsHNF
, stripTicksTop, mkInScopeSetBndrs )
import GHC.Core.FVs
import GHC.Core.Opt.Arity( collectBindersPushingCo )
+import GHC.Core.Opt.Monad
+import GHC.Core.Opt.Simplify.Env ( SimplPhase(..), isActive )
import GHC.Builtin.Types ( unboxedUnitTy )
@@ -64,9 +69,6 @@ import GHC.Core.Unfold
import Data.List( partition )
-- import Data.List.NonEmpty ( NonEmpty (..) )
-import GHC.Core.Subst (substTickish)
-import GHC.Core.TyCon (tyConClass_maybe)
-import GHC.Core.DataCon (dataConTyCon)
{-
************************************************************************
@@ -1609,7 +1611,8 @@ specCalls spec_imp env existing_rules calls_for_me fn rhs
fn_unf = realIdUnfolding fn -- Ignore loop-breaker-ness here
inl_prag = idInlinePragma fn
inl_act = inlinePragmaActivation inl_prag
- is_active = isActive (beginPhase inl_act) :: Activation -> Bool
+ is_active :: Activation -> Bool
+ is_active = isActive (SimplPhaseRange (beginPhase inl_act) (endPhase inl_act))
-- is_active: inl_act is the activation we are going to put in the new
-- SPEC rule; so we want to see if it is covered by another rule with
-- that same activation.
=====================================
compiler/GHC/Core/Opt/WorkWrap.hs
=====================================
@@ -921,10 +921,8 @@ mkStrWrapperInlinePrag (InlinePragma { inl_inline = fn_inl
-- The phase /after/ the rule is first active
get_rule_phase rule = nextPhase (beginPhase (ruleActivation rule))
-{-
-Note [Demand on the worker]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
+{- Note [Demand on the worker]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If the original function is called once, according to its demand info, then
so is the worker. This is important so that the occurrence analyser can
attach OneShot annotations to the worker’s lambda binders.
=====================================
compiler/GHC/Core/Rules.hs
=====================================
@@ -1902,7 +1902,7 @@ ruleCheckProgram :: RuleOpts -- ^ Rule options
-> (Id -> [CoreRule]) -- ^ Rules for an Id
-> CoreProgram -- ^ Bindings to check in
-> SDoc -- ^ Resulting check message
-ruleCheckProgram ropts phase rule_pat rules binds
+ruleCheckProgram ropts curr_phase rule_pat rules binds
| isEmptyBag results
= text "Rule check results: no rule application sites"
| otherwise
@@ -1912,9 +1912,9 @@ ruleCheckProgram ropts phase rule_pat rules binds
]
where
line = text (replicate 20 '-')
- env = RuleCheckEnv { rc_is_active = isActive phase
- , rc_id_unf = idUnfolding -- Not quite right
- -- Should use activeUnfolding
+ is_active = isActiveInPhase curr_phase
+ env = RuleCheckEnv { rc_is_active = is_active
+ , rc_id_unf = whenActiveUnfoldingFun is_active
, rc_pattern = rule_pat
, rc_rules = rules
, rc_ropts = ropts
=====================================
compiler/GHC/Driver/Config/Core/Lint.hs
=====================================
@@ -20,7 +20,7 @@ import GHC.Core.Lint
import GHC.Core.Lint.Interactive
import GHC.Core.Opt.Pipeline.Types
import GHC.Core.Opt.Simplify ( SimplifyOpts(..) )
-import GHC.Core.Opt.Simplify.Env ( SimplMode(..) )
+import GHC.Core.Opt.Simplify.Env ( SimplMode(..), SimplPhase(..) )
import GHC.Core.Opt.Monad
import GHC.Core.Coercion
@@ -114,9 +114,9 @@ initLintPassResultConfig dflags extra_vars pass = LintPassResultConfig
showLintWarnings :: CoreToDo -> Bool
-- Disable Lint warnings on the first simplifier pass, because
-- there may be some INLINE knots still tied, which is tiresomely noisy
-showLintWarnings (CoreDoSimplify cfg) = case sm_phase (so_mode cfg) of
- InitialPhase -> False
- _ -> True
+showLintWarnings (CoreDoSimplify cfg)
+ | SimplPhase InitialPhase <- sm_phase (so_mode cfg)
+ = False
showLintWarnings _ = True
perPassFlags :: DynFlags -> CoreToDo -> LintFlags
=====================================
compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
=====================================
@@ -10,7 +10,7 @@ import GHC.Prelude
import GHC.Core.Rules ( RuleBase )
import GHC.Core.Opt.Pipeline.Types ( CoreToDo(..) )
import GHC.Core.Opt.Simplify ( SimplifyExprOpts(..), SimplifyOpts(..) )
-import GHC.Core.Opt.Simplify.Env ( FloatEnable(..), SimplMode(..) )
+import GHC.Core.Opt.Simplify.Env ( FloatEnable(..), SimplMode(..), SimplPhase(..) )
import GHC.Core.Opt.Simplify.Monad ( TopEnvConfig(..) )
import GHC.Driver.Config ( initOptCoercionOpts )
@@ -59,7 +59,7 @@ initSimplifyOpts dflags extra_vars iterations mode hpt_rule_base = let
initSimplMode :: DynFlags -> CompilerPhase -> String -> SimplMode
initSimplMode dflags phase name = SimplMode
{ sm_names = [name]
- , sm_phase = phase
+ , sm_phase = SimplPhase phase
, sm_rules = gopt Opt_EnableRewriteRules dflags
, sm_eta_expand = gopt Opt_DoLambdaEtaExpansion dflags
, sm_cast_swizzle = True
=====================================
compiler/GHC/Hs/Binds.hs
=====================================
@@ -734,13 +734,14 @@ instance NoAnn AnnSpecSig where
data ActivationAnn
= ActivationAnn {
aa_openc :: EpToken "[",
+ aa_phase :: SourceText,
aa_closec :: EpToken "]",
aa_tilde :: Maybe (EpToken "~"),
aa_val :: Maybe EpaLocation
} deriving (Data, Eq)
instance NoAnn ActivationAnn where
- noAnn = ActivationAnn noAnn noAnn noAnn noAnn
+ noAnn = ActivationAnn noAnn NoSourceText noAnn noAnn noAnn
-- | Optional namespace specifier for fixity signatures,
=====================================
compiler/GHC/HsToCore/Quote.hs
=====================================
@@ -1189,11 +1189,11 @@ repRuleMatch ConLike = dataCon conLikeDataConName
repRuleMatch FunLike = dataCon funLikeDataConName
repPhases :: Activation -> MetaM (Core TH.Phases)
-repPhases (ActiveBefore _ i) = do { MkC arg <- coreIntLit i
- ; dataCon' beforePhaseDataConName [arg] }
-repPhases (ActiveAfter _ i) = do { MkC arg <- coreIntLit i
- ; dataCon' fromPhaseDataConName [arg] }
-repPhases _ = dataCon allPhasesDataConName
+repPhases (ActiveBefore i) = do { MkC arg <- coreIntLit i
+ ; dataCon' beforePhaseDataConName [arg] }
+repPhases (ActiveAfter i) = do { MkC arg <- coreIntLit i
+ ; dataCon' fromPhaseDataConName [arg] }
+repPhases _ = dataCon allPhasesDataConName
rep_complete_sig :: [LocatedN Name]
-> Maybe (LocatedN Name)
=====================================
compiler/GHC/Parser.y
=====================================
@@ -1949,7 +1949,7 @@ rule :: { LRuleDecl GhcPs }
, rd_bndrs = ruleBndrsOrDef $3
, rd_lhs = $4, rd_rhs = $6 }) }
--- Rules can be specified to be NeverActive, unlike inline/specialize pragmas
+-- Rules can be specified to be never active, unlike inline/specialize pragmas
rule_activation :: { (ActivationAnn, Maybe Activation) }
-- See Note [%shift: rule_activation -> {- empty -}]
: {- empty -} %shift { (noAnn, Nothing) }
@@ -1973,14 +1973,14 @@ rule_activation_marker :: { (Maybe (EpToken "~")) }
rule_explicit_activation :: { ( ActivationAnn
, Activation) } -- In brackets
- : '[' INTEGER ']' { ( ActivationAnn (epTok $1) (epTok $3) Nothing (Just (glR $2))
- , ActiveAfter (getINTEGERs $2) (fromInteger (il_value (getINTEGER $2)))) }
+ : '[' INTEGER ']' { ( ActivationAnn (epTok $1) (getINTEGERs $2) (epTok $3) Nothing (Just (glR $2))
+ , ActiveAfter (fromInteger (il_value (getINTEGER $2)))) }
| '[' rule_activation_marker INTEGER ']'
- { ( ActivationAnn (epTok $1) (epTok $4) $2 (Just (glR $3))
- , ActiveBefore (getINTEGERs $3) (fromInteger (il_value (getINTEGER $3)))) }
+ { ( ActivationAnn (epTok $1) (getINTEGERs $3) (epTok $4) $2 (Just (glR $3))
+ , ActiveBefore (fromInteger (il_value (getINTEGER $3)))) }
| '[' rule_activation_marker ']'
- { ( ActivationAnn (epTok $1) (epTok $3) $2 Nothing
- , NeverActive) }
+ { ( ActivationAnn (epTok $1) NoSourceText (epTok $3) $2 Nothing
+ , NeverActive ) }
rule_foralls :: { Maybe (RuleBndrs GhcPs) }
: 'forall' rule_vars '.' 'forall' rule_vars '.'
@@ -2825,11 +2825,11 @@ activation :: { (ActivationAnn,Maybe Activation) }
| explicit_activation { (fst $1,Just (snd $1)) }
explicit_activation :: { (ActivationAnn, Activation) } -- In brackets
- : '[' INTEGER ']' { (ActivationAnn (epTok $1) (epTok $3) Nothing (Just (glR $2))
- ,ActiveAfter (getINTEGERs $2) (fromInteger (il_value (getINTEGER $2)))) }
+ : '[' INTEGER ']' { (ActivationAnn (epTok $1) (getINTEGERs $2) (epTok $3) Nothing (Just (glR $2))
+ ,ActiveAfter (fromInteger (il_value (getINTEGER $2)))) }
| '[' rule_activation_marker INTEGER ']'
- { (ActivationAnn (epTok $1) (epTok $4) $2 (Just (glR $3))
- ,ActiveBefore (getINTEGERs $3) (fromInteger (il_value (getINTEGER $3)))) }
+ { (ActivationAnn (epTok $1) (getINTEGERs $3) (epTok $4) $2 (Just (glR $3))
+ ,ActiveBefore (fromInteger (il_value (getINTEGER $3)))) }
-----------------------------------------------------------------------------
-- Expressions
=====================================
compiler/GHC/Tc/Deriv/Generics.hs
=====================================
@@ -44,7 +44,6 @@ import GHC.Iface.Env ( newGlobalBinder )
import GHC.Types.Name hiding ( varName )
import GHC.Types.Name.Reader
-import GHC.Types.SourceText
import GHC.Types.Fixity
import GHC.Types.Basic
import GHC.Types.SrcLoc
@@ -379,7 +378,7 @@ mkBindsRep dflags gk loc dit@(DerivInstTys{dit_rep_tc = tycon}) = (binds, sigs)
max_fields = maximum $ 0 :| map dataConSourceArity datacons
inline1 f = L loc'' . InlineSig noAnn (L loc' f)
- $ alwaysInlinePragma { inl_act = ActiveAfter NoSourceText 1 }
+ $ alwaysInlinePragma { inl_act = ActiveAfter 1 }
-- The topmost M1 (the datatype metadata) has the exact same type
-- across all cases of a from/to definition, and can be factored out
=====================================
compiler/GHC/ThToHs.hs
=====================================
@@ -998,8 +998,8 @@ cvtRuleMatch TH.FunLike = Hs.FunLike
cvtPhases :: TH.Phases -> Activation -> Activation
cvtPhases AllPhases dflt = dflt
-cvtPhases (FromPhase i) _ = ActiveAfter NoSourceText i
-cvtPhases (BeforePhase i) _ = ActiveBefore NoSourceText i
+cvtPhases (FromPhase i) _ = ActiveAfter i
+cvtPhases (BeforePhase i) _ = ActiveBefore i
cvtRuleBndr :: TH.RuleBndr -> CvtM (Hs.LRuleBndr GhcPs)
cvtRuleBndr (RuleVar n)
=====================================
compiler/GHC/Types/Basic.hs
=====================================
@@ -84,11 +84,13 @@ module GHC.Types.Basic (
DefMethSpec(..),
SwapFlag(..), flipSwap, unSwap, notSwapped, isSwapped, pickSwap,
- CompilerPhase(..), PhaseNum, beginPhase, nextPhase, laterPhase,
+ CompilerPhase(..),
+ PhaseNum, nextPhase, laterPhase,
- Activation(..), isActive, competesWith,
+ Activation(..), isActiveInPhase, competesWith,
isNeverActive, isAlwaysActive, activeInFinalPhase, activeInInitialPhase,
activateAfterInitial, activateDuringFinal, activeAfter,
+ beginPhase, endPhase, laterThanPhase,
RuleMatchInfo(..), isConLike, isFunLike,
InlineSpec(..), noUserInlineSpec,
@@ -1464,52 +1466,76 @@ The CompilerPhase says which phase the simplifier is running in:
The phase sequencing is done by GHC.Opt.Simplify.Driver
-}
--- | Phase Number
-type PhaseNum = Int -- Compilation phase
- -- Phases decrease towards zero
- -- Zero is the last phase
+-- | Compilation phase number, as can be written by users in INLINE pragmas,
+-- SPECIALISE pragmas, and RULES.
+--
+-- - phases decrease towards zero
+-- - zero is the last phase
+--
+-- Does not include GHC internal "initial" and "final" phases; see 'CompilerPhase'.
+type PhaseNum = Int
+-- | Compilation phase number, including the user-specifiable 'PhaseNum'
+-- and the GHC internal "initial" and "final" phases.
data CompilerPhase
- = InitialPhase -- The first phase -- number = infinity!
- | Phase PhaseNum -- User-specificable phases
- | FinalPhase -- The last phase -- number = -infinity!
- deriving Eq
+ = InitialPhase -- ^ The first phase; number = infinity!
+ | Phase PhaseNum -- ^ User-specifiable phases
+ | FinalPhase -- ^ The last phase; number = -infinity!
+ deriving (Eq, Data)
instance Outputable CompilerPhase where
ppr (Phase n) = int n
- ppr InitialPhase = text "InitialPhase"
- ppr FinalPhase = text "FinalPhase"
+ ppr InitialPhase = text "initial"
+ ppr FinalPhase = text "final"
--- See Note [Pragma source text]
+-- | An activation is a range of phases throughout which something is active
+-- (like an INLINE pragma, SPECIALISE pragma, or RULE).
data Activation
= AlwaysActive
- | ActiveBefore SourceText PhaseNum -- Active only *strictly before* this phase
- | ActiveAfter SourceText PhaseNum -- Active in this phase and later
- | FinalActive -- Active in final phase only
+ -- | Active only *strictly before* this phase
+ | ActiveBefore PhaseNum
+ -- | Active in this phase and later phases
+ | ActiveAfter PhaseNum
+ -- | Active in the final phase only
+ | FinalActive
| NeverActive
deriving( Eq, Data )
-- Eq used in comparing rules in GHC.Hs.Decls
beginPhase :: Activation -> CompilerPhase
--- First phase in which the Activation is active
--- or FinalPhase if it is never active
+-- ^ First phase in which the 'Activation' is active,
+-- or 'FinalPhase' if it is never active
beginPhase AlwaysActive = InitialPhase
beginPhase (ActiveBefore {}) = InitialPhase
-beginPhase (ActiveAfter _ n) = Phase n
+beginPhase (ActiveAfter n) = Phase n
beginPhase FinalActive = FinalPhase
beginPhase NeverActive = FinalPhase
+endPhase :: Activation -> CompilerPhase
+-- ^ Last phase in which the 'Activation' is active,
+-- or 'InitialPhase' if it is never active
+endPhase AlwaysActive = FinalPhase
+endPhase (ActiveBefore n) =
+ if nextPhase InitialPhase == Phase n
+ then InitialPhase
+ else Phase $ n + 1
+endPhase (ActiveAfter {}) = FinalPhase
+endPhase FinalActive = FinalPhase
+endPhase NeverActive = InitialPhase
+
activeAfter :: CompilerPhase -> Activation
--- (activeAfter p) makes an Activation that is active in phase p and after
--- Invariant: beginPhase (activeAfter p) = p
+-- ^ @activeAfter p@ makes an 'Activation' that is active in phase @p@ and after
+--
+-- Invariant: @beginPhase (activeAfter p) = p@
activeAfter InitialPhase = AlwaysActive
-activeAfter (Phase n) = ActiveAfter NoSourceText n
+activeAfter (Phase n) = ActiveAfter n
activeAfter FinalPhase = FinalActive
nextPhase :: CompilerPhase -> CompilerPhase
--- Tells you the next phase after this one
--- Currently we have just phases [2,1,0,FinalPhase,FinalPhase,...]
--- Where FinalPhase means GHC's internal simplification steps
+-- ^ Tells you the next phase after this one
+--
+-- Currently we have just phases @[2,1,0,FinalPhase,FinalPhase,...]@,
+-- where FinalPhase means GHC's internal simplification steps
-- after all rules have run
nextPhase InitialPhase = Phase 2
nextPhase (Phase 0) = FinalPhase
@@ -1517,37 +1543,45 @@ nextPhase (Phase n) = Phase (n-1)
nextPhase FinalPhase = FinalPhase
laterPhase :: CompilerPhase -> CompilerPhase -> CompilerPhase
--- Returns the later of two phases
+-- ^ Returns the later of two phases
laterPhase (Phase n1) (Phase n2) = Phase (n1 `min` n2)
laterPhase InitialPhase p2 = p2
laterPhase FinalPhase _ = FinalPhase
laterPhase p1 InitialPhase = p1
laterPhase _ FinalPhase = FinalPhase
+-- | @p1 `laterThanOrEqualPhase` p2@ computes whether @p1@ happens (strictly)
+-- after @p2@.
+laterThanPhase :: CompilerPhase -> CompilerPhase -> Bool
+p1 `laterThanPhase` p2 = toNum p1 < toNum p2
+ where
+ toNum :: CompilerPhase -> Int
+ toNum InitialPhase = maxBound
+ toNum (Phase i) = i
+ toNum FinalPhase = minBound
+
activateAfterInitial :: Activation
--- Active in the first phase after the initial phase
+-- ^ Active in the first phase after the initial phase
activateAfterInitial = activeAfter (nextPhase InitialPhase)
activateDuringFinal :: Activation
--- Active in the final simplification phase (which is repeated)
+-- ^ Active in the final simplification phase (which is repeated)
activateDuringFinal = FinalActive
-isActive :: CompilerPhase -> Activation -> Bool
-isActive InitialPhase act = activeInInitialPhase act
-isActive (Phase p) act = activeInPhase p act
-isActive FinalPhase act = activeInFinalPhase act
+isActiveInPhase :: CompilerPhase -> Activation -> Bool
+isActiveInPhase InitialPhase act = activeInInitialPhase act
+isActiveInPhase (Phase p) act = activeInPhase p act
+isActiveInPhase FinalPhase act = activeInFinalPhase act
activeInInitialPhase :: Activation -> Bool
-activeInInitialPhase AlwaysActive = True
-activeInInitialPhase (ActiveBefore {}) = True
-activeInInitialPhase _ = False
+activeInInitialPhase act = beginPhase act == InitialPhase
activeInPhase :: PhaseNum -> Activation -> Bool
-activeInPhase _ AlwaysActive = True
-activeInPhase _ NeverActive = False
-activeInPhase _ FinalActive = False
-activeInPhase p (ActiveAfter _ n) = p <= n
-activeInPhase p (ActiveBefore _ n) = p > n
+activeInPhase _ AlwaysActive = True
+activeInPhase _ NeverActive = False
+activeInPhase _ FinalActive = False
+activeInPhase p (ActiveAfter n) = p <= n
+activeInPhase p (ActiveBefore n) = p > n
activeInFinalPhase :: Activation -> Bool
activeInFinalPhase AlwaysActive = True
@@ -1562,25 +1596,19 @@ isNeverActive _ = False
isAlwaysActive AlwaysActive = True
isAlwaysActive _ = False
-competesWith :: Activation -> Activation -> Bool
+-- | @act1 `competesWith` act2@ returns whether @act1@ is active in the phase
+-- when @act2@ __becomes__ active.
+--
+-- This answers the question: might @act1@ fire first?
+--
+-- NB: this is not the same as computing whether @act1@ and @act2@ are
+-- ever active at the same time.
+--
-- See Note [Competing activations]
-competesWith AlwaysActive _ = True
-
-competesWith NeverActive _ = False
-competesWith _ NeverActive = False
-
-competesWith FinalActive FinalActive = True
-competesWith FinalActive _ = False
-
-competesWith (ActiveBefore {}) AlwaysActive = True
-competesWith (ActiveBefore {}) FinalActive = False
-competesWith (ActiveBefore {}) (ActiveBefore {}) = True
-competesWith (ActiveBefore _ a) (ActiveAfter _ b) = a < b
-
-competesWith (ActiveAfter {}) AlwaysActive = False
-competesWith (ActiveAfter {}) FinalActive = True
-competesWith (ActiveAfter {}) (ActiveBefore {}) = False
-competesWith (ActiveAfter _ a) (ActiveAfter _ b) = a >= b
+competesWith :: Activation -> Activation -> Bool
+competesWith NeverActive _ = False
+competesWith _ NeverActive = False -- See Wrinkle [Never active rules]
+competesWith act1 act2 = isActiveInPhase (beginPhase act2) act1
{- Note [Competing activations]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1595,8 +1623,20 @@ It's too conservative to ensure that the two are never simultaneously
active. For example, a rule might be always active, and an inlining
might switch on in phase 2. We could switch off the rule, but it does
no harm.
--}
+ Wrinkle [Never active rules]
+
+ Rules can be declared as "never active" by users, using the syntax:
+
+ {-# RULE "blah" [~] ... #-}
+
+ (This feature exists solely for compiler plugins, by making it possible
+ to define a RULE that is never run by GHC, but is nevertheless parsed,
+ typechecked etc, so that it is available to the plugin.)
+
+ We should not warn about competing rules, so make sure that 'competesWith'
+ always returns 'False' when its second argument is 'NeverActive'.
+-}
{- *********************************************************************
* *
@@ -1855,26 +1895,36 @@ setInlinePragmaRuleMatchInfo :: InlinePragma -> RuleMatchInfo -> InlinePragma
setInlinePragmaRuleMatchInfo prag info = prag { inl_rule = info }
instance Outputable Activation where
- ppr AlwaysActive = empty
- ppr NeverActive = brackets (text "~")
- ppr (ActiveBefore _ n) = brackets (char '~' <> int n)
- ppr (ActiveAfter _ n) = brackets (int n)
- ppr FinalActive = text "[final]"
+ ppr AlwaysActive = empty
+ ppr NeverActive = brackets (text "~")
+ ppr (ActiveBefore n) = brackets (char '~' <> int n)
+ ppr (ActiveAfter n) = brackets (int n)
+ ppr FinalActive = text "[final]"
+
+instance Binary CompilerPhase where
+ put_ bh InitialPhase = putByte bh 0
+ put_ bh (Phase i) = do { putByte bh 1; put_ bh i }
+ put_ bh FinalPhase = putByte bh 2
+
+ get bh = do
+ h <- getByte bh
+ case h of
+ 0 -> return InitialPhase
+ 1 -> do { p <- get bh; return (Phase p) }
+ _ -> return FinalPhase
instance Binary Activation where
put_ bh NeverActive =
putByte bh 0
- put_ bh FinalActive =
+ put_ bh FinalActive = do
putByte bh 1
put_ bh AlwaysActive =
putByte bh 2
- put_ bh (ActiveBefore src aa) = do
+ put_ bh (ActiveBefore aa) = do
putByte bh 3
- put_ bh src
put_ bh aa
- put_ bh (ActiveAfter src ab) = do
+ put_ bh (ActiveAfter ab) = do
putByte bh 4
- put_ bh src
put_ bh ab
get bh = do
h <- getByte bh
@@ -1882,19 +1932,21 @@ instance Binary Activation where
0 -> return NeverActive
1 -> return FinalActive
2 -> return AlwaysActive
- 3 -> do src <- get bh
- aa <- get bh
- return (ActiveBefore src aa)
- _ -> do src <- get bh
- ab <- get bh
- return (ActiveAfter src ab)
-
+ 3 -> do aa <- get bh
+ return (ActiveBefore aa)
+ _ -> do ab <- get bh
+ return (ActiveAfter ab)
+instance NFData CompilerPhase where
+ rnf = \case
+ InitialPhase -> ()
+ FinalPhase -> ()
+ Phase i -> rnf i
instance NFData Activation where
rnf = \case
AlwaysActive -> ()
NeverActive -> ()
- ActiveBefore src aa -> rnf src `seq` rnf aa
- ActiveAfter src ab -> rnf src `seq` rnf ab
+ ActiveBefore aa -> rnf aa
+ ActiveAfter ab -> rnf ab
FinalActive -> ()
instance Outputable RuleMatchInfo where
=====================================
compiler/GHC/Types/Id/Make.hs
=====================================
@@ -67,7 +67,6 @@ import GHC.Core.Class
import GHC.Core.DataCon
import GHC.Types.Literal
-import GHC.Types.SourceText
import GHC.Types.RepType ( countFunRepArgs, typePrimRep )
import GHC.Types.Name.Set
import GHC.Types.Name
@@ -1926,8 +1925,7 @@ seqId = pcRepPolyId seqName ty concs info
`setArityInfo` arity
inline_prag
- = alwaysInlinePragma `setInlinePragmaActivation` ActiveAfter
- NoSourceText 0
+ = alwaysInlinePragma `setInlinePragmaActivation` ActiveAfter 0
-- Make 'seq' not inline-always, so that simpleOptExpr
-- (see GHC.Core.Subst.simple_app) won't inline 'seq' on the
-- LHS of rules. That way we can have rules for 'seq';
=====================================
compiler/GHC/Utils/Binary.hs
=====================================
@@ -1869,172 +1869,6 @@ instance Binary ModuleName where
put_ bh (ModuleName fs) = put_ bh fs
get bh = do fs <- get bh; return (ModuleName fs)
--- instance Binary TupleSort where
--- put_ bh BoxedTuple = putByte bh 0
--- put_ bh UnboxedTuple = putByte bh 1
--- put_ bh ConstraintTuple = putByte bh 2
--- get bh = do
--- h <- getByte bh
--- case h of
--- 0 -> do return BoxedTuple
--- 1 -> do return UnboxedTuple
--- _ -> do return ConstraintTuple
-
--- instance Binary Activation where
--- put_ bh NeverActive = do
--- putByte bh 0
--- put_ bh FinalActive = do
--- putByte bh 1
--- put_ bh AlwaysActive = do
--- putByte bh 2
--- put_ bh (ActiveBefore src aa) = do
--- putByte bh 3
--- put_ bh src
--- put_ bh aa
--- put_ bh (ActiveAfter src ab) = do
--- putByte bh 4
--- put_ bh src
--- put_ bh ab
--- get bh = do
--- h <- getByte bh
--- case h of
--- 0 -> do return NeverActive
--- 1 -> do return FinalActive
--- 2 -> do return AlwaysActive
--- 3 -> do src <- get bh
--- aa <- get bh
--- return (ActiveBefore src aa)
--- _ -> do src <- get bh
--- ab <- get bh
--- return (ActiveAfter src ab)
-
--- instance Binary InlinePragma where
--- put_ bh (InlinePragma s a b c d) = do
--- put_ bh s
--- put_ bh a
--- put_ bh b
--- put_ bh c
--- put_ bh d
-
--- get bh = do
--- s <- get bh
--- a <- get bh
--- b <- get bh
--- c <- get bh
--- d <- get bh
--- return (InlinePragma s a b c d)
-
--- instance Binary RuleMatchInfo where
--- put_ bh FunLike = putByte bh 0
--- put_ bh ConLike = putByte bh 1
--- get bh = do
--- h <- getByte bh
--- if h == 1 then return ConLike
--- else return FunLike
-
--- instance Binary InlineSpec where
--- put_ bh NoUserInlinePrag = putByte bh 0
--- put_ bh Inline = putByte bh 1
--- put_ bh Inlinable = putByte bh 2
--- put_ bh NoInline = putByte bh 3
-
--- get bh = do h <- getByte bh
--- case h of
--- 0 -> return NoUserInlinePrag
--- 1 -> return Inline
--- 2 -> return Inlinable
--- _ -> return NoInline
-
--- instance Binary RecFlag where
--- put_ bh Recursive = do
--- putByte bh 0
--- put_ bh NonRecursive = do
--- putByte bh 1
--- get bh = do
--- h <- getByte bh
--- case h of
--- 0 -> do return Recursive
--- _ -> do return NonRecursive
-
--- instance Binary OverlapMode where
--- put_ bh (NoOverlap s) = putByte bh 0 >> put_ bh s
--- put_ bh (Overlaps s) = putByte bh 1 >> put_ bh s
--- put_ bh (Incoherent s) = putByte bh 2 >> put_ bh s
--- put_ bh (Overlapping s) = putByte bh 3 >> put_ bh s
--- put_ bh (Overlappable s) = putByte bh 4 >> put_ bh s
--- get bh = do
--- h <- getByte bh
--- case h of
--- 0 -> (get bh) >>= \s -> return $ NoOverlap s
--- 1 -> (get bh) >>= \s -> return $ Overlaps s
--- 2 -> (get bh) >>= \s -> return $ Incoherent s
--- 3 -> (get bh) >>= \s -> return $ Overlapping s
--- 4 -> (get bh) >>= \s -> return $ Overlappable s
--- _ -> panic ("get OverlapMode" ++ show h)
-
-
--- instance Binary OverlapFlag where
--- put_ bh flag = do put_ bh (overlapMode flag)
--- put_ bh (isSafeOverlap flag)
--- get bh = do
--- h <- get bh
--- b <- get bh
--- return OverlapFlag { overlapMode = h, isSafeOverlap = b }
-
--- instance Binary FixityDirection where
--- put_ bh InfixL = do
--- putByte bh 0
--- put_ bh InfixR = do
--- putByte bh 1
--- put_ bh InfixN = do
--- putByte bh 2
--- get bh = do
--- h <- getByte bh
--- case h of
--- 0 -> do return InfixL
--- 1 -> do return InfixR
--- _ -> do return InfixN
-
--- instance Binary Fixity where
--- put_ bh (Fixity src aa ab) = do
--- put_ bh src
--- put_ bh aa
--- put_ bh ab
--- get bh = do
--- src <- get bh
--- aa <- get bh
--- ab <- get bh
--- return (Fixity src aa ab)
-
--- instance Binary WarningTxt where
--- put_ bh (WarningTxt s w) = do
--- putByte bh 0
--- put_ bh s
--- put_ bh w
--- put_ bh (DeprecatedTxt s d) = do
--- putByte bh 1
--- put_ bh s
--- put_ bh d
-
--- get bh = do
--- h <- getByte bh
--- case h of
--- 0 -> do s <- get bh
--- w <- get bh
--- return (WarningTxt s w)
--- _ -> do s <- get bh
--- d <- get bh
--- return (DeprecatedTxt s d)
-
--- instance Binary StringLiteral where
--- put_ bh (StringLiteral st fs _) = do
--- put_ bh st
--- put_ bh fs
--- get bh = do
--- st <- get bh
--- fs <- get bh
--- return (StringLiteral st fs Nothing)
-
newtype BinLocated a = BinLocated { unBinLocated :: Located a }
instance Binary a => Binary (BinLocated a) where
=====================================
hie.yaml
=====================================
@@ -5,4 +5,4 @@
# cradle: {bios: {program: "./hadrian/hie-bios.bat"}}
#
# The format is documented here - https://github.com/mpickering/hie-bios
-cradle: {bios: {program: "./hadrian/hie-bios"}}
+cradle: {bios: {program: "./hadrian/hie-bios.bat"}}
=====================================
testsuite/tests/perf/compiler/T4007.stdout
=====================================
@@ -1,6 +1,9 @@
Rule fired: Class op foldr (BUILTIN)
Rule fired: Class op return (BUILTIN)
Rule fired: unpack (GHC.Internal.Base)
+Rule fired: repeat (GHC.Internal.List)
+Rule fired: take (GHC.Internal.List)
+Rule fired: fold/build (GHC.Internal.Base)
Rule fired: fold/build (GHC.Internal.Base)
Rule fired: Class op >> (BUILTIN)
Rule fired: SPEC/T4007 sequence__c @IO @_ @_ (T4007)
=====================================
testsuite/tests/simplCore/should_compile/T15056.stderr
=====================================
@@ -5,4 +5,5 @@ Rule fired: Class op + (BUILTIN)
Rule fired: +# (BUILTIN)
Rule fired: Class op foldr (BUILTIN)
Rule fired: Class op enumFromTo (BUILTIN)
+Rule fired: eftInt (GHC.Internal.Enum)
Rule fired: fold/build (GHC.Internal.Base)
=====================================
testsuite/tests/simplCore/should_compile/T15445.stderr
=====================================
@@ -6,9 +6,11 @@ Rule fired: USPEC $fShowList @Int (GHC.Internal.Show)
Rule fired: Class op >> (BUILTIN)
Rule fired: USPEC plusTwoRec @Int (T15445a)
Rule fired: Class op enumFromTo (BUILTIN)
+Rule fired: eftInt (GHC.Internal.Enum)
Rule fired: Class op show (BUILTIN)
Rule fired: USPEC plusTwoRec @Int (T15445a)
Rule fired: Class op enumFromTo (BUILTIN)
+Rule fired: eftInt (GHC.Internal.Enum)
Rule fired: Class op show (BUILTIN)
Rule fired: eftIntList (GHC.Internal.Enum)
Rule fired: ># (BUILTIN)
=====================================
testsuite/tests/simplCore/should_compile/T26323b.hs
=====================================
@@ -0,0 +1,24 @@
+module T26323b where
+
+f :: Int -> Int
+f _ = 0
+{-# NOINLINE f #-}
+
+g :: Int -> Int
+g _ = 1
+{-# NOINLINE g #-}
+
+h :: Int -> Int
+h _ = 2
+{-# NOINLINE h #-}
+
+-- These two RULES loop, but that's OK because they are never active
+-- at the same time.
+{-# RULES "t1" [1] forall x. g x = f x #-}
+{-# RULES "t2" [~1] forall x. f x = g x #-}
+
+-- Make sure we don't fire "t1" and "t2" in a loop in the RHS of a never-active rule.
+{-# RULES "t" [~] forall x. h x = f x #-}
+
+test :: Int
+test = f 4 + g 5 + h 6
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -537,6 +537,7 @@ test('T25389', normal, compile, ['-O -ddump-simpl -dsuppress-uniques -dno-typeab
test('T24359a', normal, compile, ['-O -ddump-rules'])
test('T24606', [grep_errmsg(r'fAlternativeRWST')], compile, ['-O -ddump-simpl -dsuppress-uniques -dsuppress-idinfo -dsuppress-coercions -dsuppress-coercion-types'])
test('T25713', [grep_errmsg('W:::')], compile, ['-O -ddump-simpl'])
+test('T26323b', normal, compile, ['-O'])
test('T25883', normal, compile_grep_core, [''])
test('T25883b', normal, compile_grep_core, [''])
=====================================
testsuite/tests/simplCore/should_run/T26323.hs
=====================================
@@ -0,0 +1,32 @@
+module Main where
+
+f :: Int -> Int
+f x = g x
+{-# INLINE [1] f #-}
+
+g :: Int -> Int
+g x = 0
+{-# NOINLINE g #-}
+
+h :: Int -> Int
+h _ = 1
+{-# NOINLINE h #-}
+
+{-# RULES "r1" [2] forall x. g x = h x #-}
+{-# RULES "r2" [~1] forall x. h x = 2 #-}
+
+test :: Int
+test = f 3
+
+main :: IO ()
+main = print test
+ -- we should get
+ --
+ -- f 3
+ -- ==> inline in phase 1
+ -- g 3
+ -- ==> use 'r1' in phase 1
+ -- h 3
+ -- = 1
+ --
+ -- Here rule 'r2' should never fire, so we SHOULD NOT rewrite 'h 3' to '2'.
=====================================
testsuite/tests/simplCore/should_run/T26323.stdout
=====================================
@@ -0,0 +1 @@
+1
=====================================
testsuite/tests/simplCore/should_run/all.T
=====================================
@@ -93,6 +93,7 @@ test('T17151', [], multimod_compile_and_run, ['T17151', ''])
test('T18012', normal, compile_and_run, [''])
test('T17744', normal, compile_and_run, [''])
test('T18638', normal, compile_and_run, [''])
+test('T26323', normal, compile_and_run, ['-O'])
test('NumConstantFolding8', normal, compile_and_run, [''])
test('NumConstantFolding16', normal, compile_and_run, [''])
test('NumConstantFolding32', normal, compile_and_run, [''])
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -2010,25 +2010,27 @@ instance ExactPrint (RuleDecl GhcPs) where
markActivation :: (Monad m, Monoid w)
=> ActivationAnn -> Activation -> EP w m ActivationAnn
-markActivation (ActivationAnn o c t v) act = do
+markActivation (ActivationAnn o src c t v) act = do
case act of
- ActiveBefore src phase -> do
+ ActiveBefore phase -> do
o' <- markEpToken o -- '['
t' <- mapM markEpToken t -- ~
v' <- mapM (\val -> printStringAtAA val (toSourceTextWithSuffix src (show phase) "")) v
c' <- markEpToken c -- ']'
- return (ActivationAnn o' c' t' v')
- ActiveAfter src phase -> do
+ return (ActivationAnn o' src c' t' v')
+ ActiveAfter phase -> do
o' <- markEpToken o -- '['
v' <- mapM (\val -> printStringAtAA val (toSourceTextWithSuffix src (show phase) "")) v
c' <- markEpToken c -- ']'
- return (ActivationAnn o' c' t v')
+ return (ActivationAnn o' src c' t v')
NeverActive -> do
o' <- markEpToken o -- '['
t' <- mapM markEpToken t -- ~
c' <- markEpToken c -- ']'
- return (ActivationAnn o' c' t' v)
- _ -> return (ActivationAnn o c t v)
+ return (ActivationAnn o' src c' t' v)
+
+ -- Other activations don't have corresponding source syntax
+ _ -> return (ActivationAnn o src c t v)
-- ---------------------------------------------------------------------
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2da84b7a83f723dc6531cdad5ef3c7e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/2da84b7a83f723dc6531cdad5ef3c7e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0