[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 9 commits: Ensure TcM plugins are only initialised once
by Marge Bot (@marge-bot) 27 Apr '26
by Marge Bot (@marge-bot) 27 Apr '26
27 Apr '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
a779ff92 by sheaf at 2026-04-27T04:31:50-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
fe8ba1c9 by sheaf at 2026-04-27T04:31:55-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
7f79d0e0 by sheaf at 2026-04-27T04:32:00-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
201feff6 by Wen Kokke at 2026-04-27T04:32:06-04:00
rts: Add dynamic trace flags API
This commit adds an API to the RTS (exposed via Rts.h) that allows users to dynamically change the trace flags.
Prior to this commit, users were able to stop and start the profiling and heap profiling timers (via startProfTimer/stopProfTimer and startHeapProfTimer/stopHeapProfTimer).
This extends that functionality to also cover the core event types.
The getTraceFlag/setTraceFlag functions read and write the values of the trace flag cache, which is allocated by Trace.c, rather than modifying the members of RtsFlags.TraceFlags.
This is done under the assumption that the members of RtsFlags should not be modified after RTS initialisation.
Consequently, if the user modifies the trace flags using setTraceFlag, the object returned by getTraceFlags (from base) will not reflect these changes.
The trace flags are not protected by locks of any sort.
Hence, these functions are not thread-safe.
However, the trace flags are not modified by the RTS after initialisation, only read, so the race conditions introduced by one user modifying them are most likely benign.
This PR also puts the trace flag cache in a single global struct, as opposed to a collection of global variables, and changes the types of the individual flags from uint8_t to bool, as these have the same size on both Clang and GCC and are a better semantic match.
Prior to the change to uint8_t, they had type int, see 42c47cd6.
Even with its deprecation in C23, I don't think there should be any issue depending on stdbool.h.
The TRACE_X macros are redefined to access the global struct, with values cast to const bool to ensure they are read-only.
- - - - -
b2466164 by Wen Kokke at 2026-04-27T04:32:06-04:00
rts: Ensure TRACE_X values are used in place of RtsFlags.TraceFlags.X
- - - - -
224c2c4d by Wen Kokke at 2026-04-27T04:32:06-04:00
rts: Fix nonmoving-GC tracing
The current nonmoving-GC tracing functions were written in a different
style from the other tracing functions. They were directly implemented
as, e.g., a traceConcMarkEnd function that called postConcMarkEnd.
The other tracing functions are implemented as, e.g., traceThreadLabel_,
a function that posts the thread label event, and traceThreadLabel, a
macro that checks whether TRACE_scheduler is set. This commit fixes that
implementation, and ensures that the nonmoving-GC tracing functions only
emit events if nonmoving-GC tracing is enabled.
- - - - -
a3758bb0 by Wen Kokke at 2026-04-27T04:32:06-04:00
rts: Add SymI_HasProto for get/setTraceFlag
- - - - -
b74cc5d6 by Wen Kokke at 2026-04-27T04:32:07-04:00
rts: Add SymI_HasProto for start/endEventLogging
- - - - -
5078b9d2 by Simon Peyton Jones at 2026-04-27T04:32:07-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
75 changed files:
- + changelog.d/hadrian-response-files.md
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI/Info.hs
- hadrian/build-cabal.bat
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7ee8d844ee946f8a2dbf50309aac3a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7ee8d844ee946f8a2dbf50309aac3a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 9 commits: Ensure TcM plugins are only initialised once
by Marge Bot (@marge-bot) 27 Apr '26
by Marge Bot (@marge-bot) 27 Apr '26
27 Apr '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
a9f0437f by sheaf at 2026-04-26T23:44:27-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
3cb43683 by sheaf at 2026-04-26T23:44:33-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
f3d61e46 by sheaf at 2026-04-26T23:44:37-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
6bd3b96f by Wen Kokke at 2026-04-26T23:44:41-04:00
rts: Add dynamic trace flags API
This commit adds an API to the RTS (exposed via Rts.h) that allows users to dynamically change the trace flags.
Prior to this commit, users were able to stop and start the profiling and heap profiling timers (via startProfTimer/stopProfTimer and startHeapProfTimer/stopHeapProfTimer).
This extends that functionality to also cover the core event types.
The getTraceFlag/setTraceFlag functions read and write the values of the trace flag cache, which is allocated by Trace.c, rather than modifying the members of RtsFlags.TraceFlags.
This is done under the assumption that the members of RtsFlags should not be modified after RTS initialisation.
Consequently, if the user modifies the trace flags using setTraceFlag, the object returned by getTraceFlags (from base) will not reflect these changes.
The trace flags are not protected by locks of any sort.
Hence, these functions are not thread-safe.
However, the trace flags are not modified by the RTS after initialisation, only read, so the race conditions introduced by one user modifying them are most likely benign.
This PR also puts the trace flag cache in a single global struct, as opposed to a collection of global variables, and changes the types of the individual flags from uint8_t to bool, as these have the same size on both Clang and GCC and are a better semantic match.
Prior to the change to uint8_t, they had type int, see 42c47cd6.
Even with its deprecation in C23, I don't think there should be any issue depending on stdbool.h.
The TRACE_X macros are redefined to access the global struct, with values cast to const bool to ensure they are read-only.
- - - - -
c14f0fc4 by Wen Kokke at 2026-04-26T23:44:41-04:00
rts: Ensure TRACE_X values are used in place of RtsFlags.TraceFlags.X
- - - - -
95340c85 by Wen Kokke at 2026-04-26T23:44:41-04:00
rts: Fix nonmoving-GC tracing
The current nonmoving-GC tracing functions were written in a different
style from the other tracing functions. They were directly implemented
as, e.g., a traceConcMarkEnd function that called postConcMarkEnd.
The other tracing functions are implemented as, e.g., traceThreadLabel_,
a function that posts the thread label event, and traceThreadLabel, a
macro that checks whether TRACE_scheduler is set. This commit fixes that
implementation, and ensures that the nonmoving-GC tracing functions only
emit events if nonmoving-GC tracing is enabled.
- - - - -
2c35fe8f by Wen Kokke at 2026-04-26T23:44:42-04:00
rts: Add SymI_HasProto for get/setTraceFlag
- - - - -
d98a5b0b by Wen Kokke at 2026-04-26T23:44:42-04:00
rts: Add SymI_HasProto for start/endEventLogging
- - - - -
7ee8d844 by Simon Peyton Jones at 2026-04-26T23:44:42-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
75 changed files:
- + changelog.d/hadrian-response-files.md
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI/Info.hs
- hadrian/build-cabal.bat
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1f4d2ef1e23fdb2c5a68dc21d45789…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1f4d2ef1e23fdb2c5a68dc21d45789…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26989] 2 commits: Update stderr tests
by Simon Peyton Jones (@simonpj) 26 Apr '26
by Simon Peyton Jones (@simonpj) 26 Apr '26
26 Apr '26
Simon Peyton Jones pushed to branch wip/T26989 at Glasgow Haskell Compiler / GHC
Commits:
d2ad273a by Simon Peyton Jones at 2026-04-26T17:50:21+01:00
Update stderr tests
...mainly as a result of printing names for dead lambda binders
(A debug-output change only.)
- - - - -
9e642e00 by Simon Peyton Jones at 2026-04-27T00:11:49+01:00
Add MOutCoercion to ApplyToVal
Nicer... but lets see what CI says
- - - - -
25 changed files:
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- testsuite/tests/codeGen/should_compile/T25177.stderr
- testsuite/tests/deSugar/should_compile/T13208.stdout
- testsuite/tests/numeric/should_compile/T15547.stderr
- testsuite/tests/numeric/should_compile/T20347.stderr
- testsuite/tests/numeric/should_compile/T20374.stderr
- testsuite/tests/numeric/should_compile/T20376.stderr
- testsuite/tests/printer/T18052a.stderr
- testsuite/tests/simplCore/should_compile/DsSpecPragmas.stderr
- testsuite/tests/simplCore/should_compile/RewriteHigherOrderPatterns.stderr
- testsuite/tests/simplCore/should_compile/T18668.stderr
- testsuite/tests/simplCore/should_compile/T19246.stderr
- testsuite/tests/simplCore/should_compile/T19599.stderr
- testsuite/tests/simplCore/should_compile/T19599a.stderr
- testsuite/tests/simplCore/should_compile/T21917.stderr
- testsuite/tests/simplCore/should_compile/T23074.stderr
- testsuite/tests/simplCore/should_compile/T25160.stderr
- testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-64
- testsuite/tests/simplCore/should_compile/T26051.stderr
- testsuite/tests/simplCore/should_compile/T26116.stderr
- testsuite/tests/simplCore/should_compile/T8331.stderr
- testsuite/tests/simplCore/should_compile/T8848a.stderr
- testsuite/tests/typecheck/should_compile/T13032.stderr
Changes:
=====================================
compiler/GHC/Core/Opt/Simplify/Env.hs
=====================================
@@ -28,7 +28,7 @@ module GHC.Core.Opt.Simplify.Env (
SimplEnvIS, checkSimplEnvIS, pprBadSimplEnvIS,
-- * Substitution results
- SimplSR(..), mkContEx, substId, lookupRecBndr,
+ SimplSR(..), substId, lookupRecBndr,
-- * Simplifying 'Id' binders
simplNonRecBndr, simplNonRecJoinBndr, simplRecBndrs, simplRecJoinBndrs,
@@ -488,12 +488,11 @@ data SimplSR
-- and v is a join-point of arity a
-- <=> x is a join-point of arity a
- | ContEx TvSubstEnv -- A suspended substitution
- CvSubstEnv
- SimplIdSubst
+ | ContEx SimplEnv
InExpr
- -- If x :-> ContEx tv cv id e is in the SimplISubst
- -- then replace occurrences of x by (subst (tv,cv,id) e)
+ MOutCoercion
+ -- If x :-> ContEx static_env e mco is in the SimplISubst
+ -- then replace occurrences of x by (subst (tv,cv,id) e) |> mco
instance Outputable SimplSR where
ppr (DoneId v) = text "DoneId" <+> ppr v
@@ -503,8 +502,8 @@ instance Outputable SimplSR where
NotJoinPoint -> empty
JoinPoint n -> parens (int n)
- ppr (ContEx _tv _cv _id e) = vcat [text "ContEx" <+> ppr e {-,
- ppr (filter_env tv), ppr (filter_env id) -}]
+ ppr (ContEx _env e _mco) = text "ContEx" <+> ppr e
+ -- ppr (filter_env tv), ppr (filter_env id)
-- where
-- fvs = exprFreeVars e
-- filter_env env = filterVarEnv_Directly keep env
@@ -736,9 +735,6 @@ zapSubstEnv env@(SimplEnv { seInlineDepth = n })
setSubstEnv :: SimplEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> SimplEnv
setSubstEnv env tvs cvs ids = env { seTvSubst = tvs, seCvSubst = cvs, seIdSubst = ids }
-mkContEx :: SimplEnv -> InExpr -> SimplSR
-mkContEx (SimplEnv { seTvSubst = tvs, seCvSubst = cvs, seIdSubst = ids }) e = ContEx tvs cvs ids e
-
{-
************************************************************************
* *
@@ -1368,17 +1364,15 @@ getTCvSubst (SimplEnv { seInScope = in_scope, seTvSubst = tv_env, seCvSubst = cv
getFullSubst :: InScopeSet -> SimplEnv -> Subst
getFullSubst in_scope (SimplEnv { seIdSubst = id_env, seTvSubst = tv_env, seCvSubst = cv_env })
- = mk_full_subst in_scope tv_env cv_env id_env
-
-mk_full_subst :: InScopeSet -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> Subst
-mk_full_subst in_scope tv_env cv_env id_env
= mkSubst in_scope (mapVarEnv to_expr id_env) tv_env cv_env
where
to_expr :: SimplSR -> CoreExpr
-- A tiresome impedence-matcher
- to_expr (DoneEx e _) = e
- to_expr (DoneId v) = Var v
- to_expr (ContEx tvs cvs ids e) = GHC.Core.Subst.substExprSC (mk_full_subst in_scope tvs cvs ids) e
+ to_expr (DoneEx e _) = e
+ to_expr (DoneId v) = Var v
+ to_expr (ContEx env e mco) = mkCastMCo e' mco
+ where
+ e' = GHC.Core.Subst.substExprSC (getFullSubst in_scope env) e
substTy :: HasDebugCallStack => SimplEnv -> Type -> Type
substTy env ty = Type.substTy (getTCvSubst env) ty
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -283,7 +283,7 @@ simplRecOrTopPair :: SimplEnv
simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs
| Just env' <- preInlineUnconditionally env (bindContextLevel bind_cxt)
- old_bndr rhs (UnSimplified env)
+ old_bndr (UnSimplified env) rhs MRefl
= {-#SCC "simplRecOrTopPair-pre-inline-uncond" #-}
simplTrace "SimplBindr:inline-uncond1" (ppr old_bndr) $
do { tick (PreInlineUnconditionally old_bndr)
@@ -1263,7 +1263,7 @@ simplExprF1 env (App fun arg) cont
simplExprF env fun $
ApplyToVal { sc_arg = arg, sc_env = UnSimplified env
, sc_hole_ty = substTy env (exprType fun)
- , sc_cont = cont }
+ , sc_cast = MRefl, sc_cont = cont }
simplExprF1 env expr@(Lam {}) cont
= {-#SCC "simplExprF1-Lam" #-}
@@ -1298,7 +1298,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont
do { ty' <- simplType env ty
; simplExprF (extendTvSubst env bndr ty') body cont }
- | Just env' <- preInlineUnconditionally env NotTopLevel bndr rhs (UnSimplified env)
+ | Just env' <- preInlineUnconditionally env NotTopLevel bndr (UnSimplified env) rhs MRefl
-- Because of the let-can-float invariant, it's ok to
-- inline freely, or to drop the binding if it is dead.
= do { simplTrace "SimplBindr:inline-uncond2" (ppr bndr) $
@@ -1606,10 +1606,10 @@ rebuild_go env expr cont
ApplyToTy { sc_arg_ty = ty, sc_cont = cont}
-> rebuild_go env (App expr (Type ty)) cont
- ApplyToVal { sc_arg = arg, sc_env = se
+ ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
, sc_cont = cont, sc_hole_ty = fun_ty }
-- See Note [Avoid redundant simplification]
- -> do { (_, arg') <- simplArg env fun_ty Nothing se arg
+ -> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
; rebuild_go env (App expr arg') cont }
completeBindX :: SimplEnv
@@ -1728,6 +1728,11 @@ optOutCoercion env co already_optimised
empty_subst = mkEmptySubst (seInScope env)
opts = seOptCoercionOpts env
+addCastMCo :: MOutCoercion -> SimplCont -> SimplCont
+-- Simpler version of `pushCast` when optionally want to add a cast to the top
+addCastMCo MRefl cont = cont
+addCastMCo (MCo co) cont = CastIt { sc_co = co, sc_opt = False, sc_cont = cont }
+
pushCast :: SimplEnv -> OutCoercion -> SimplCont -> SimplM SimplCont
pushCast env co cont
= go co True cont
@@ -1753,8 +1758,7 @@ pushCast env co cont
-- co1 :: t1 ~ s1
-- co2 :: s2 ~ t2
go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
- , sc_cont = tail
- , sc_hole_ty = fun_ty })
+ , sc_cast = arg_mco, sc_cont = tail })
| not co_is_opt
= -- pushCoValArg duplicates the coercion, so optimise first
go (optOutCoercion (zapSubstEnv env) co co_is_opt) True cont
@@ -1762,22 +1766,11 @@ pushCast env co cont
| Just (m_co1, m_co2) <- pushCoValArg co
= {-#SCC "addCoerce-pushCoValArg" #-}
do { tail' <- go_mco m_co2 co_is_opt tail
- ; case m_co1 of {
- MRefl -> return (cont { sc_cont = tail'
- , sc_hole_ty = coercionLKind co }) ;
- -- See Note [Avoiding simplifying repeatedly]
-
- MCo co1 ->
- do { (arg_se', arg') <- simplArg env fun_ty Nothing arg_se arg
- -- When we build the ApplyTo we can't mix the OutCoercion
- -- 'co' with the InExpr 'arg', so we simplify
- -- to make it all consistent. It's a bit messy.
- -- But it isn't a common case.
- -- Example of use: #995
- ; return (ApplyToVal { sc_arg = mkCast arg' co1
- , sc_env = arg_se'
+ ; return (ApplyToVal { sc_arg = arg
+ , sc_env = arg_se
+ , sc_cast = m_co1 `mkTransMCo` arg_mco
, sc_cont = tail'
- , sc_hole_ty = coercionLKind co }) } } }
+ , sc_hole_ty = coercionLKind co }) }
go co co_is_opt cont
| isReflCo co = return cont -- Having this at the end makes a huge
@@ -1793,25 +1786,24 @@ pushCast env co cont
go_mco (MCo co) opt cont = go co opt cont
simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet
- -> OutType -- ^ Type of the function applied to this arg
-> Maybe ArgInfo -- ^ Just <=> This arg `ai` occurs in an app
-- `f a1 ... an` where we have ArgInfo on
-- how `f` uses `ai`, affecting the Stop
-- continuation passed to 'simplExprC'
+ -> OutType -- ^ Type of the function applied to this arg
-> StaticEnv -> CoreExpr -- ^ Expression with its static envt
- -> SimplM (StaticEnv, OutExpr)
-simplArg _ _ _ se@(Simplified {}) arg
- = return (se, arg)
-simplArg env fun_ty mb_arg_info (UnSimplified arg_se) arg
+ -> MOutCoercion -- Wrap this around the result
+ -> SimplM OutExpr
+simplArg _ _ _ (Simplified {}) arg mco
+ = return (mkCastMCo arg mco)
+simplArg env mb_arg_info fun_ty (UnSimplified arg_se) arg mco
= do { let arg_env' = arg_se `setInScopeFromE` env
arg_ty = funArgTy fun_ty
stop = case mb_arg_info of
- Nothing -> mkBoringStop arg_ty
- Just ai -> mkLazyArgStop arg_ty ai
- ; arg' <- simplExprC arg_env' arg stop
- ; return (Simplified NoDup, arg') }
- -- Return a StaticEnv that includes the in-scope set from 'env',
- -- because arg' may well mention those variables (#20639)
+ Nothing -> mkBoringStop arg_ty
+ Just ai -> mkLazyArgStop arg_ty ai
+ cont = addCastMCo mco stop
+ ; simplExprC arg_env' arg cont }
{-
************************************************************************
@@ -1844,54 +1836,67 @@ simpl_lam env bndr body (ApplyToTy { sc_arg_ty = arg_ty, sc_cont = cont })
= do { tick (BetaReduction bndr)
; simplLam (extendTvSubst env bndr arg_ty) body cont }
+{- Next case handles this
-- Coercion beta-reduction
simpl_lam env bndr body (ApplyToVal { sc_arg = Coercion arg_co, sc_env = arg_se
- , sc_cont = cont })
+ , sc_cast = arg_mco, sc_cont = cont })
+ | let arg_co' = case arg_se of
+ Simplified {} -> arg_co
+ UnSimplified arg_se -> substCo (arg_se `setInScopeFromE` env) arg_co
+ , Just final_arg_co <- case mco of -- C.f. GHC.Core.Utils.mkCast
+ MRefl -> Just arg_co'
+ MCo co' | isEqPred (coercionRKind co')
+ -> Just (mkCoCast arg_co' co')
+ | otherwise
+ -> Nothing
= assertPpr (isCoVar bndr) (ppr bndr) $
do { tick (BetaReduction bndr)
- ; let arg_co' = case arg_se of
- Simplified {} -> arg_co
- UnSimplified arg_se -> substCo (arg_se `setInScopeFromE` env) arg_co
; simplLam (extendCvSubst env bndr arg_co') body cont }
+-}
-- Value beta-reduction
-- This works for /coercion/ lambdas too
simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
- , sc_cont = cont
+ , sc_cast = arg_mco, sc_cont = cont
, sc_hole_ty = fun_ty})
- = do { tick (BetaReduction bndr)
- ; let from_what = FromBeta arg_levity
- arg_levity
- | isForAllTy fun_ty = assertPpr (isCoVar bndr) (ppr bndr) Unlifted
- | otherwise = typeLevity (funArgTy fun_ty)
- -- Example: (\(cv::a ~# b). blah) co
- -- The type of (\cv.blah) can be (forall cv. ty); see GHC.Core.Utils.mkLamType
-
- -- Using fun_ty: see Note [Dark corner with representation polymorphism]
- -- e.g (\r \(a::TYPE r) \(x::a). blah) @LiftedRep @Int arg
- -- When we come to `x=arg` we must choose lazy/strict correctly
- -- It's wrong to err in either direction
- -- But fun_ty is an OutType, so is fully substituted
-
- ; if | Just env' <- preInlineUnconditionally env NotTopLevel bndr arg arg_se
- , not (needsCaseBindingL arg_levity arg)
+ | Just env' <- preInlineUnconditionally env NotTopLevel bndr arg_se arg arg_mco
+ , not (needsCaseBindingL arg_levity arg)
-- Ok to test arg::InExpr in needsCaseBinding because
-- exprOkForSpeculation is stable under simplification
- -> do { simplTrace "SimplBindr:inline-uncond3" (ppr bndr <+> text ":=" <+> ppr arg $$ ppr (seIdSubst env)) $
- tick (PreInlineUnconditionally bndr)
- ; simplLam env' body cont }
-
- | otherwise
- -> case arg_se of
- Simplified {}
- -- Don't re-simplify if we've simplified it once
- -- Including don't preInlineUnconditionally
- -- See Note [Avoiding simplifying repeatedly]
- -> completeBindX env from_what bndr arg body cont
-
- UnSimplified arg_env
- -> simplNonRecE env from_what bndr (arg, arg_env) body cont
+ = simplTrace "SimplBindr:inline-uncond3"
+ (vcat [ ppr bndr <+> text ":=" <+> ppr arg
+ , ppr (seIdSubst env) ]) $
+ do { tick (BetaReduction bndr)
+ ; tick (PreInlineUnconditionally bndr)
+ ; simplLam env' body cont }
+
+ | otherwise
+ = do { tick (BetaReduction bndr)
+ ; let from_what = FromBeta arg_levity
+
+ ; case (arg_se, arg_mco) of
+ (UnSimplified arg_env, MRefl)
+ -- Optimisation: when there is no wrapping coercion use simplNonRecE
+ -- so that the clever floating out of let-bindings can take place
+ -- in this round of the Simplifier
+ -> simplNonRecE env from_what bndr (arg, arg_env) body cont
+
+ _ -> do { arg' <- simplArg env Nothing fun_ty arg_se arg arg_mco
+ ; completeBindX env from_what bndr arg' body cont }
}
+ where
+ arg_levity
+ | isForAllTy fun_ty = assertPpr (isCoVar bndr) (ppr bndr) Unlifted
+ | otherwise = typeLevity (funArgTy fun_ty)
+ -- Example: (\(cv::a ~# b). blah) co
+ -- The type of (\cv.blah) can be (forall cv. ty); see GHC.Core.Utils.mkLamType
+
+ -- Using fun_ty: see Note [Dark corner with representation polymorphism]
+ -- e.g (\r \(a::TYPE r) \(x::a). blah) @LiftedRep @Int arg
+ -- When we come to `x=arg` we must choose lazy/strict correctly
+ -- It's wrong to err in either direction
+ -- But fun_ty is an OutType, so is fully substituted
+
-- Discard a non-counting tick on a lambda. This may change the
-- cost attribution slightly (moving the allocation of the
@@ -2289,17 +2294,18 @@ simplInId env var cont
= rebuild env (Var var) cont
| otherwise
= case substId env var of
- ContEx tvs cvs ids e -> simplExprF env' e cont
+ ContEx se e mco
+ -> simplExprF (se `setInScopeFromE` env) e (addCastMCo mco cont)
-- Don't trimJoinCont; haven't already simplified e,
-- so the cont is not embodied in e
- where
- env' = setSubstEnv env tvs cvs ids
- DoneId out_id -> simplOutId zapped_env out_id cont'
+ DoneId out_id
+ -> simplOutId zapped_env out_id cont'
where
cont' = trimJoinCont out_id (idJoinPointHood out_id) cont
- DoneEx e mb_join -> simplOutExpr zapped_env e cont'
+ DoneEx e mb_join
+ -> simplOutExpr zapped_env e cont'
where
cont' = trimJoinCont var mb_join cont
where
@@ -2353,12 +2359,12 @@ simplOutId :: SimplEnvIS -> OutId -> SimplCont -> SimplM (SimplFloats, OutExpr)
-- See Note [Simplification of runRW#] in GHC.CoreToSTG.Prep.
--
-- runRW# :: forall (r :: RuntimeRep) (o :: TYPE r). (State# RealWorld -> o) -> o
--- K[ runRW# @rr @hole_ty body ] --> runRW @rr' @ty' (\s. K[ body s ])
+-- K[ runRW# @rr @hole_ty arg ] --> runRW @rr' @ty' (\s. K[ arg s ])
simplOutId env fun cont
| fun `hasKey` runRWKey
, ApplyToTy { sc_cont = cont1 } <- cont
, ApplyToTy { sc_cont = cont2, sc_arg_ty = hole_ty } <- cont1
- , ApplyToVal { sc_cont = cont3, sc_arg = arg
+ , ApplyToVal { sc_cont = cont3, sc_arg = arg, sc_cast = arg_mco
, sc_env = arg_se, sc_hole_ty = fun_ty } <- cont2
-- Do this even if (contIsStop cont), or if seCaseCase is off.
-- See Note [No eta-expansion in runRW#]
@@ -2387,7 +2393,8 @@ simplOutId env fun cont
_ -> do { s' <- newId (fsLit "s") ManyTy realWorldStatePrimTy
; let (m,_,_) = splitFunTy fun_ty
env' = arg_env `addNewInScopeIds` [s']
- cont' = ApplyToVal { sc_arg = Var s'
+ cont' = addCastMCo arg_mco $
+ ApplyToVal { sc_arg = Var s', sc_cast = MRefl
, sc_env = Simplified OkDup, sc_cont = inner_cont
, sc_hole_ty = mkVisFunTy m realWorldStatePrimTy new_runrw_res_ty }
-- cont' applies to s', then K
@@ -2472,16 +2479,17 @@ rebuildCall env info (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_c
---------- Simplify value arguments --------------------
rebuildCall env fun_info
- (ApplyToVal { sc_arg = arg, sc_env = arg_se
+ (ApplyToVal { sc_arg = arg, sc_env = arg_se, sc_cast = arg_mco
, sc_hole_ty = fun_ty, sc_cont = cont })
| UnSimplified arg_env <- arg_se
, isStrictArgInfo fun_info -- Strict arguments
, seCaseCase env -- But only when case-of-case is on.
-- See Note [Case-of-case and full laziness]
- = simplExprF (arg_env `setInScopeFromE` env) arg
- (StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
- , sc_dup = NoDup
- , sc_cont = cont })
+ = simplExprF (arg_env `setInScopeFromE` env) arg $
+ addCastMCo arg_mco $
+ StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
+ , sc_dup = NoDup
+ , sc_cont = cont }
-- Note [Shadowing in the Simplifier]
| otherwise -- Lazy, or already simplified arguments
@@ -2489,7 +2497,7 @@ rebuildCall env fun_info
-- There is no benefit (unlike in a let-binding), and we'd
-- have to be very careful about bogus strictness through
-- floating a demanded let.
- = do { (_, arg') <- simplArg env fun_ty (Just fun_info) arg_se arg
+ = do { arg' <- simplArg env (Just fun_info) fun_ty arg_se arg arg_mco
; rebuildCall env (addValArgTo fun_info arg' fun_ty) cont }
---------- No further useful info, revert to generic rebuild ------------
@@ -2804,6 +2812,7 @@ trySeqRules in_env scrut rhs cont
, as_dmd = seqDmd
, as_hole_ty = res3_ty } ]
rule_cont = ApplyToVal { sc_env = UnSimplified in_env, sc_arg = rhs
+ , sc_cast = MRefl
, sc_cont = cont, sc_hole_ty = res4_ty }
out_args = [Type rhs_rep, Type scrut_ty, Type rhs_ty, no_cast_scrut]
@@ -3900,7 +3909,8 @@ knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont
return ( emptyFloats env
, extendIdSubst env case_bndr (DoneEx scrut NotJoinPoint))
- | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr con_app (UnSimplified env)
+ | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr
+ (UnSimplified env) con_app MRefl
= return (emptyFloats env', env')
| otherwise
@@ -4088,7 +4098,7 @@ mkDupableContWithDmds env dmds
, sc_arg_ty = arg_ty, sc_hole_ty = hole_ty }) }
mkDupableContWithDmds env dmds
- (ApplyToVal { sc_arg = arg, sc_env = se
+ (ApplyToVal { sc_arg = arg, sc_env = se, sc_cast = arg_mco
, sc_cont = cont, sc_hole_ty = hole_ty })
= -- e.g. [...hole...] (...arg...)
-- ==>
@@ -4098,12 +4108,12 @@ mkDupableContWithDmds env dmds
do { let dmd:|cont_dmds = expectNonEmpty dmds
; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
; let env' = env `setInScopeFromF` floats1
- ; (_, arg') <- simplArg env' hole_ty Nothing se arg
+ ; arg' <- simplArg env' Nothing hole_ty se arg arg_mco
; (let_floats2, triv_arg) <- makeTrivial env' NotTopLevel dmd (fsLit "karg") arg'
; let all_floats = floats1 `addLetFloats` let_floats2
; return ( all_floats
, ApplyToVal { sc_arg = triv_arg, sc_env = Simplified OkDup
- , sc_cont = cont', sc_hole_ty = hole_ty }) }
+ , sc_cast = MRefl, sc_cont = cont', sc_hole_ty = hole_ty }) }
mkDupableContWithDmds env _
(Select { sc_bndr = case_bndr, sc_alts = alts, sc_env = se, sc_cont = cont })
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -172,10 +172,11 @@ data SimplCont
, sc_cont :: SimplCont }
| ApplyToVal -- (ApplyToVal arg K)[e] = K[ e arg ]
- { sc_hole_ty :: OutType -- Type of the function, presumably (forall a. blah)
- -- See Note [The hole type in ApplyToTy]
- , sc_env :: StaticEnv -- See Note [StaticEnv]
- , sc_arg :: CoreExpr -- The argument,
+ { sc_hole_ty :: OutType -- Type of the function, presumably (forall a. blah)
+ -- See Note [The hole type in ApplyToTy]
+ , sc_env :: StaticEnv -- See Note [StaticEnv]
+ , sc_arg :: CoreExpr -- The argument
+ , sc_cast :: MOutCoercion -- Wrap this OutCoercion around the (simplified) argument
, sc_cont :: SimplCont }
| ApplyToTy -- (ApplyToTy ty K)[e] = K[ e ty ]
@@ -416,7 +417,7 @@ pushArgs fun_ty (arg:args) cont
= ApplyToTy { sc_hole_ty = fun_ty, sc_arg_ty = ty
, sc_cont = pushArgs (piResultTy fun_ty ty) args cont }
| otherwise
- = ApplyToVal { sc_hole_ty = fun_ty
+ = ApplyToVal { sc_hole_ty = fun_ty, sc_cast = MRefl
, sc_arg = arg, sc_env = Simplified NoDup
, sc_cont = pushArgs (funResultTy fun_ty) args cont}
@@ -428,7 +429,7 @@ pushArgSpec :: ArgSpec -> SimplCont -> SimplCont
pushArgSpec (TyArg { as_arg_ty = arg_ty, as_hole_ty = hole_ty }) cont
= ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = cont }
pushArgSpec (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
- = ApplyToVal { sc_arg = arg, sc_env = Simplified NoDup
+ = ApplyToVal { sc_arg = arg, sc_env = Simplified NoDup, sc_cast = MRefl
, sc_hole_ty = hole_ty, sc_cont = cont }
argSpecArg :: ArgSpec -> OutExpr
@@ -1083,8 +1084,8 @@ interestingArg env se e
go env n (Var v)
= case substId env v of
DoneId v' -> go_var n v'
- DoneEx e _ -> go (zapSubstEnv env) n e
- ContEx tvs cvs ids e -> go (setSubstEnv env tvs cvs ids) n e
+ DoneEx e _ -> go (zapSubstEnv env) n e
+ ContEx se e _mco -> go (se `setInScopeFromE` env) n e
go _ _ (Lit l)
| isLitRubbish l = NonTrivArg -- See (IA3) in Note [Interesting arguments]
@@ -1585,13 +1586,13 @@ the former.
preInlineUnconditionally
:: SimplEnv -> TopLevelFlag -> InId
- -> InExpr -> StaticEnv -- These two go together
+ -> StaticEnv -> CoreExpr -> MOutCoercion -- The argument
-> Maybe SimplEnv -- Returned env has extended substitution
-- Precondition: rhs satisfies the let-can-float invariant
-- See Note [Core let-can-float invariant] in GHC.Core
-- Reason: we don't want to inline single uses, or discard dead bindings,
-- for unlifted, side-effect-ful bindings
-preInlineUnconditionally env top_lvl bndr rhs rhs_se
+preInlineUnconditionally env top_lvl bndr rhs_se rhs rhs_mco
| not pre_inline_unconditionally = Nothing
| not active = Nothing
| isTopLevel top_lvl && isDeadEndId bndr = Nothing -- Note [Top-level bottoming Ids]
@@ -1603,7 +1604,8 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_se
-- See Note [Stable unfoldings and preInlineUnconditionally]
| not (isInlinePragma inline_prag)
- , Just inl <- maybeUnfoldingTemplate unf = Just $! (extend_subst_with inl)
+ , Just inl <- maybeUnfoldingTemplate unf = assertPpr (isReflMCo rhs_mco) (ppr bndr) $
+ Just $! (extend_subst_with inl)
| otherwise = Nothing
where
@@ -1613,9 +1615,10 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_se
-- If not then ContEx
-- ToDo: flesh this note out
extend_subst_with inl_rhs
- = case rhs_se of
- Simplified _ -> extendIdSubst env bndr $! DoneEx inl_rhs NotJoinPoint
- UnSimplified rhs_env -> extendIdSubst env bndr $! mkContEx rhs_env inl_rhs
+ = extendIdSubst env bndr $!
+ case rhs_se of
+ Simplified _ -> DoneEx (mkCastMCo inl_rhs rhs_mco) NotJoinPoint
+ UnSimplified rhs_env -> ContEx rhs_env inl_rhs rhs_mco
one_occ IAmDead = True -- Happens in ((\x.1) v)
one_occ OneOcc{ occ_n_br = 1
=====================================
testsuite/tests/codeGen/should_compile/T25177.stderr
=====================================
@@ -9,7 +9,7 @@ d = D 10## RUBBISH(IntRep)
lvl = foo d
-bar1 = \ _ eta -> case lvl of { W# ipv -> (# eta, () #) }
+bar1 = \ x eta -> case lvl of { W# ipv -> (# eta, () #) }
bar = bar1 `cast` <Co:6> :: ...
=====================================
testsuite/tests/deSugar/should_compile/T13208.stdout
=====================================
@@ -1,6 +1,6 @@
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=1,unsat_ok=True,boring_ok=True)}]
-f = \ (@p) _ [Occ=Dead] -> GHC.Internal.Types.True
+f = \ (@p) (x [Occ=Dead] :: p) -> GHC.Internal.Types.True
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
=====================================
testsuite/tests/numeric/should_compile/T15547.stderr
=====================================
@@ -4,28 +4,28 @@ Result size of Tidy Core
= {terms: 40, types: 122, coercions: 26, joins: 0/0}
nat2Word#
- = \ @n $dKnownNat _ ->
+ = \ @n $dKnownNat p1 ->
naturalToWord# ((natSing $dKnownNat) `cast` <Co:2> :: ...)
-foo = \ _ -> 18##
+foo = \ ds -> 18##
fd
- = \ @n $dKnownNat _ ->
+ = \ @n $dKnownNat ds ->
naturalToWord# ((natSing $dKnownNat) `cast` <Co:6> :: ...)
-d = \ _ -> 3##
+d = \ ds -> 3##
fm
- = \ @n $dKnownNat _ ->
+ = \ @n $dKnownNat ds ->
naturalToWord# ((natSing $dKnownNat) `cast` <Co:8> :: ...)
-m = \ _ -> 9##
+m = \ ds -> 9##
fp
- = \ @n $dKnownNat _ ->
+ = \ @n $dKnownNat ds ->
naturalToWord# ((natSing $dKnownNat) `cast` <Co:10> :: ...)
-p = \ _ -> 512##
+p = \ ds -> 512##
=====================================
testsuite/tests/numeric/should_compile/T20347.stderr
=====================================
@@ -5,7 +5,7 @@ Result size of Tidy Core
foo0 = \ x -> -# 10# x
-foo1 = \ _ -> 10#
+foo1 = \ x -> 10#
foo2 = \ x -> +# 10# x
=====================================
testsuite/tests/numeric/should_compile/T20374.stderr
=====================================
@@ -3,15 +3,15 @@
Result size of Tidy Core
= {terms: 44, types: 107, coercions: 0, joins: 0/0}
-foo0 = \ _ -> (# 0#, 0#, 683234160# #)
+foo0 = \ ds -> (# 0#, 0#, 683234160# #)
-foo1 = \ _ -> (# 0#, -1#, -683234160# #)
+foo1 = \ ds -> (# 0#, -1#, -683234160# #)
foo2 = foo0
foo3 = foo1
-foo4 = \ _ -> (# 0#, 0#, 0# #)
+foo4 = \ ds -> (# 0#, 0#, 0# #)
foo5 = foo4
@@ -19,11 +19,11 @@ foo6 = \ other -> other
foo7 = foo6
-foo8 = \ _ -> (# 0#, 0#, 128# #)
+foo8 = \ ds -> (# 0#, 0#, 128# #)
-foo9 = \ _ -> (# 0#, -1#, -128# #)
+foo9 = \ ds -> (# 0#, -1#, -128# #)
-foo10 = \ _ -> 1#
+foo10 = \ ds -> 1#
=====================================
testsuite/tests/numeric/should_compile/T20376.stderr
=====================================
@@ -3,11 +3,11 @@
Result size of Tidy Core
= {terms: 71, types: 45, coercions: 0, joins: 0/0}
-foo0 = \ _ -> 16##
+foo0 = \ ds -> 16##
-foo1 = \ _ -> 4##
+foo1 = \ ds -> 4##
-foo2 = \ _ -> 11##
+foo2 = \ ds -> 11##
foo3 = foo0
@@ -21,11 +21,11 @@ foo3' = foo0'
foo4' = I# 31#
-ctz0 = \ _ -> 30##
+ctz0 = \ ds -> 30##
-ctz1 = \ _ -> 6##
+ctz1 = \ ds -> 6##
-ctz2 = \ _ -> 14##
+ctz2 = \ ds -> 14##
ctz3 = ctz0
@@ -39,11 +39,11 @@ ctz3' = ctz0'
ctz4' = I# 62#
-clz1 = \ _ -> 5##
+clz1 = \ ds -> 5##
-clz2 = \ _ -> 13##
+clz2 = \ ds -> 13##
-clz3 = \ _ -> 29##
+clz3 = \ ds -> 29##
clz1' = I# 5#
=====================================
testsuite/tests/printer/T18052a.stderr
=====================================
@@ -6,7 +6,7 @@ TYPE CONSTRUCTORS
PATTERN SYNONYMS
(:||:) :: forall {a} {b}. a -> b -> (a, b)
Dependent modules: []
-Dependent packages: [(normal, base-4.21.0.0)]
+Dependent packages: [(normal, base-4.23.0.0)]
==================== Tidy Core ====================
Result size of Tidy Core
@@ -35,7 +35,7 @@ T18052a.$m:||:
(@b)
(scrut :: (a, b))
(cont :: a -> b -> r)
- _ [Occ=Dead] ->
+ (fail [Occ=Dead] :: (# #) -> r) ->
case scrut of { (x, y) -> cont x y }
=====================================
testsuite/tests/simplCore/should_compile/DsSpecPragmas.stderr
=====================================
@@ -1,78 +1,102 @@
==================== Tidy Core rules ====================
"USPEC f1 @Word @[e]"
- forall (@e) ($dNum :: Num Word) ($dEq :: Eq [e]).
+ forall (@e) ($dNum [Occ=Dead] :: Num Word) ($dEq :: Eq [e]).
f1 @Word @[e] $dNum $dEq
- = \ _ [Occ=Dead] _ [Occ=Dead] -> I# 111#
+ = \ (ds [Occ=Dead] :: Word) (ds1 [Occ=Dead] :: [e]) -> I# 111#
"USPEC f1 @Word @_"
- forall (@e) ($dNum :: Num Word) ($dEq :: Eq e).
+ forall (@e) ($dNum [Occ=Dead] :: Num Word) ($dEq :: Eq e).
f1 @Word @e $dNum $dEq
- = \ _ [Occ=Dead] _ [Occ=Dead] -> I# 111#
+ = \ (ds [Occ=Dead] :: Word) (ds1 [Occ=Dead] :: e) -> I# 111#
"USPEC f1_qc @_ @(g e) @Word"
forall (@(g :: * -> *))
(@e)
(df :: forall x. Eq x => Eq (g x))
($dEq :: Eq (g e))
- ($dNum :: Num Word).
+ ($dNum [Occ=Dead] :: Num Word).
f1_qc @g @(g e) @Word df $dEq $dNum
- = \ _ [Occ=Dead] _ [Occ=Dead] _ [Occ=Dead] -> C# 'q'#
+ = \ (ds [Occ=Dead] :: Proxy g)
+ (ds1 [Occ=Dead] :: g e)
+ (ds2 [Occ=Dead] :: Word) ->
+ C# 'q'#
"USPEC f2 @_ @_ @Word"
- forall (@c) ($dEq :: Eq c) ($dEq1 :: Eq c) ($dNum :: Num Word).
+ forall (@c)
+ ($dEq [Occ=Dead] :: Eq c)
+ ($dEq1 :: Eq c)
+ ($dNum [Occ=Dead] :: Num Word).
f2 @c @c @Word $dEq $dEq1 $dNum
- = \ _ [Occ=Dead] _ [Occ=Dead] _ [Occ=Dead] -> I# 2#
+ = \ (ds [Occ=Dead] :: c)
+ (ds1 [Occ=Dead] :: c)
+ (ds2 [Occ=Dead] :: Word) ->
+ I# 2#
"USPEC f3 @Int @_"
forall (@(g :: * -> *))
- ($dEq :: Eq Int)
+ ($dEq [Occ=Dead] :: Eq Int)
(df :: forall x. Eq x => Eq (g x)).
f3 @Int @g $dEq df
= f3_$sf3 @g df
"USPEC f3 @_ @[]"
- forall (@c) ($dEq :: Eq c) (df :: forall x. Eq x => Eq [x]).
+ forall (@c)
+ ($dEq :: Eq c)
+ (df [Occ=Dead] :: forall x. Eq x => Eq [x]).
f3 @c @[] $dEq df
= f3_$sf1 @c $dEq
"USPEC f4 @_ @(ST s)"
- forall (@b) (@s) ($dEq :: Eq b) ($dMonad :: Monad (ST s)).
+ forall (@b)
+ (@s)
+ ($dEq :: Eq b)
+ ($dMonad [Occ=Dead] :: Monad (ST s)).
f4 @b @(ST s) $dEq $dMonad
= $fApplicativeST_$cpure @s @b
"USPEC f4_qc @Int @_ @_"
forall (@(r :: (* -> *) -> * -> *))
(@(n :: * -> *))
- ($dEq :: Eq Int)
+ ($dEq [Occ=Dead] :: Eq Int)
(df :: forall (m :: * -> *). Monad m => Monad (r m)).
f4_qc @Int @r @n $dEq df
- = \ _ [Occ=Dead] -> ()
+ = \ (ds [Occ=Dead] :: r n Int) -> ()
"USPEC f5 @(D Int)"
- forall ($dEq :: Eq (D Int)). f5 @(D Int) $dEq = f5_$sf5
+ forall ($dEq [Occ=Dead] :: Eq (D Int)). f5 @(D Int) $dEq = f5_$sf5
"USPEC f5_qc @Int @D"
- forall ($dEq :: Eq Int)
- ($dEq1 :: Eq (T Int))
- (df :: forall x. (Eq x, Eq (T x)) => Eq (D x)).
+ forall ($dEq [Occ=Dead] :: Eq Int)
+ ($dEq1 [Occ=Dead] :: Eq (T Int))
+ (df [Occ=Dead] :: forall x. (Eq x, Eq (T x)) => Eq (D x)).
f5_qc @Int @D $dEq $dEq1 df
= f5_$sf5
"USPEC f5_qc @Int @_"
forall (@(g :: * -> *))
- ($dEq :: Eq Int)
- ($dEq1 :: Eq (T Int))
+ ($dEq [Occ=Dead] :: Eq Int)
+ ($dEq1 [Occ=Dead] :: Eq (T Int))
(df :: forall x. (Eq x, Eq (T x)) => Eq (g x)).
f5_qc @Int @g $dEq $dEq1 df
= f5_qc_$sf5_qc @g df
"USPEC f6 @_ @_ @Word"
- forall (@c) ($dEq :: Eq c) ($dOrd :: Ord c) ($dNum :: Num Word).
+ forall (@c)
+ ($dEq [Occ=Dead] :: Eq c)
+ ($dOrd :: Ord c)
+ ($dNum [Occ=Dead] :: Num Word).
f6 @c @c @Word $dEq $dOrd $dNum
- = \ _ [Occ=Dead] _ [Occ=Dead] _ [Occ=Dead] -> C# 'c'#
+ = \ (ds [Occ=Dead] :: c)
+ (ds1 [Occ=Dead] :: c)
+ (ds2 [Occ=Dead] :: Word) ->
+ C# 'c'#
"USPEC f6_qc @_ @_ @Word"
forall (@(h :: * -> *))
- (df :: forall x. Eq x => Eq (h x))
+ (df [Occ=Dead] :: forall x. Eq x => Eq (h x))
(df1 :: forall y. Eq y => Ord (h y))
- ($dNum :: Num Word).
+ ($dNum [Occ=Dead] :: Num Word).
f6_qc @h @h @Word df df1 $dNum
- = \ _ [Occ=Dead] _ [Occ=Dead] _ [Occ=Dead] -> C# 'd'#
+ = \ (ds [Occ=Dead] :: Proxy h)
+ (ds1 [Occ=Dead] :: Proxy h)
+ (ds2 [Occ=Dead] :: Word) ->
+ C# 'd'#
"USPEC f7 @Int"
- forall ($dCls :: Cls (TF Int)) ($dEq :: Eq Int).
+ forall ($dCls :: Cls (TF Int)) ($dEq [Occ=Dead] :: Eq Int).
f7 @Int $dCls $dEq
= \ (x [Occ=Once1] :: Int) -> x
"USPEC qcfd @C @G"
- forall ($dF :: F C G) (df :: forall a b. C (a, b)).
+ forall ($dF [Occ=Dead] :: F C G)
+ (df [Occ=Dead] :: forall a b. C (a, b)).
qcfd @C @G $dF df
= qcfd_x
=====================================
testsuite/tests/simplCore/should_compile/RewriteHigherOrderPatterns.stderr
=====================================
@@ -3,28 +3,28 @@ Rule fired
Module: (RewriteHigherOrderPatterns)
Full arity: 1
Before: bar \ x y z -> two (two x y) z
- After: (\ f -> True) (\ x y -> two (two x y))
+ After: (\ f -> True) (\ x y -> two (two x y))
Rule fired
Rule: bar
Module: (RewriteHigherOrderPatterns)
Full arity: 1
- Before: bar \ x _ z -> two (two x (I# 2#)) z
- After: (\ f -> True) (\ x _ -> two (two x (I# 2#)))
+ Before: bar \ x y z -> two (two x (I# 2#)) z
+ After: (\ f -> True) (\ x y -> two (two x (I# 2#)))
Rule fired
Rule: foo
Module: (RewriteHigherOrderPatterns)
Full arity: 1
Before: foo \ x -> two (two x (I# 2#)) x
- After: (\ f -> True) (\ x -> two (two x (I# 2#)) x)
+ After: (\ f -> True) (\ x -> two (two x (I# 2#)) x)
Rule fired
Rule: qux
Module: (RewriteHigherOrderPatterns)
Full arity: 1
Before: qux \ x y -> three (two x (I# 1#)) (I# 2#) y
- After: (\ f -> True) (\ x -> three (two x (I# 1#)))
+ After: (\ f -> True) (\ x -> three (two x (I# 1#)))
Rule fired
Rule: baz
Module: (RewriteHigherOrderPatterns)
Full arity: 1
Before: baz \ x -> three (two x (I# 1#)) (I# 2#) x
- After: (\ f -> True) (\ x -> three (two x (I# 1#)) (I# 2#))
+ After: (\ f -> True) (\ x -> three (two x (I# 1#)) (I# 2#))
=====================================
testsuite/tests/simplCore/should_compile/T18668.stderr
=====================================
@@ -3,23 +3,24 @@ Rule fired
Module: (T18668)
Full arity: 0
Before: GHC.Internal.Prim.+# 2# 3#
- After: GHC.Internal.Prim.*#
+ After: GHC.Internal.Prim.*#
Rule fired
Rule: *#
Module: (BUILTIN)
Full arity: 2
Before: GHC.Internal.Prim.*# 2# 3#
- After: 6#
+ After: 6#
Rule fired
Rule: flip
Module: (T18668)
Full arity: 1
Before: GHC.Internal.Prim.># 1# 0#
- After: (\ (x :: GHC.Internal.Prim.Int#) -> GHC.Internal.Prim.<# x)
- 1#
+ After: (\ (x [Occ=Once1] :: GHC.Internal.Prim.Int#) ->
+ GHC.Internal.Prim.<# x)
+ 1#
Rule fired
Rule: <#
Module: (BUILTIN)
Full arity: 2
Before: GHC.Internal.Prim.<# 1# 0#
- After: 0#
+ After: 0#
=====================================
testsuite/tests/simplCore/should_compile/T19246.stderr
=====================================
@@ -5,7 +5,8 @@
==================== Tidy Core rules ====================
"SPEC/T19246 $wf @Int" [2]
- forall ($dOrd :: Ord Int). $wf @Int $dOrd = $s$wf
-"USPEC f @Int" [2] forall ($dOrd :: Ord Int). f @Int $dOrd = $sf
+ forall ($dOrd [Occ=Dead] :: Ord Int). $wf @Int $dOrd = $s$wf
+"USPEC f @Int" [2]
+ forall ($dOrd [Occ=Dead] :: Ord Int). f @Int $dOrd = $sf
=====================================
testsuite/tests/simplCore/should_compile/T19599.stderr
=====================================
@@ -1,6 +1,8 @@
==================== Tidy Core rules ====================
"SPEC myShow_impl @Int"
- forall ($dMyShow :: MyShow Int). myShow_impl @Int $dMyShow = foo
+ forall ($dMyShow [Occ=Dead] :: MyShow Int).
+ myShow_impl @Int $dMyShow
+ = foo
=====================================
testsuite/tests/simplCore/should_compile/T19599a.stderr
=====================================
@@ -1,6 +1,6 @@
==================== Tidy Core rules ====================
"SPEC r_bar @Int"
- forall ($dC :: C Int). r_bar @Int $dC = $fCInt_$sr_bar
+ forall ($dC [Occ=Dead] :: C Int). r_bar @Int $dC = $fCInt_$sr_bar
=====================================
testsuite/tests/simplCore/should_compile/T21917.stderr
=====================================
@@ -1,7 +1,8 @@
==================== Tidy Core rules ====================
"SPEC foo @IO @Int"
- forall ($dMonad :: Monad IO) ($dIntegral :: Integral Int).
+ forall ($dMonad [Occ=Dead] :: Monad IO)
+ ($dIntegral [Occ=Dead] :: Integral Int).
foo1 @IO @Int $dMonad $dIntegral
= foo_$sfoo
=====================================
testsuite/tests/simplCore/should_compile/T23074.stderr
=====================================
@@ -1,7 +1,7 @@
==================== Tidy Core rules ====================
"SPEC $cstimes @Int"
- forall ($dIntegral :: Integral Int).
+ forall ($dIntegral [Occ=Dead] :: Integral Int).
$fSemigroupSumInt_$cstimes @Int $dIntegral
= foo
=====================================
testsuite/tests/simplCore/should_compile/T25160.stderr
=====================================
@@ -1,5 +1,6 @@
==================== Tidy Core rules ====================
-"USPEC bar @_" forall (@a) ($dC :: C a). bar @a $dC = bar_$sbar @a
+"USPEC bar @_"
+ forall (@a) ($dC [Occ=Dead] :: C a). bar @a $dC = bar_$sbar @a
=====================================
testsuite/tests/simplCore/should_compile/T25718c.stderr-ws-64
=====================================
@@ -3,37 +3,37 @@
Result size of Tidy Core
= {terms: 161, types: 140, coercions: 0, joins: 0/0}
-narrow8_ge_lb = \ _ -> True
+narrow8_ge_lb = \ x -> True
narrow8_le_ub = narrow8_ge_lb
-narrow8_gt_ub_false = \ _ -> False
+narrow8_gt_ub_false = \ x -> False
narrow16_ge_lb = narrow8_ge_lb
narrow16_le_ub = narrow8_ge_lb
-narrow8w_lt_ub = \ _ -> True
+narrow8w_lt_ub = \ x -> True
narrow16w_lt_ub = narrow8w_lt_ub
-word16_lt_ub = \ _ -> True
+word16_lt_ub = \ x -> True
-word16_ge_ub_false = \ _ -> False
+word16_ge_ub_false = \ x -> False
word_to_word8_lt = narrow8w_lt_ub
word_to_word16_lt = narrow8w_lt_ub
-word8_to_int8_ge = \ _ -> True
+word8_to_int8_ge = \ x -> True
word16_to_int16_ge = word16_lt_ub
-int8_to_word8_le = \ _ -> True
+int8_to_word8_le = \ x -> True
-int16_to_word16_le = \ _ -> True
+int16_to_word16_le = \ x -> True
-word8_add_lt_256 = \ _ _ -> True
+word8_add_lt_256 = \ x y -> True
word16_alts
= \ x ->
@@ -51,15 +51,15 @@ narrow8_alts
word8_sub_lt_256 = word8_add_lt_256
-word16_add_lt_ub = \ _ _ -> True
+word16_add_lt_ub = \ x y -> True
word16_sub_lt_ub = word16_add_lt_ub
-int8_add_ge_lb = \ _ _ -> True
+int8_add_ge_lb = \ x y -> True
int8_sub_le_ub = int8_add_ge_lb
-int16_add_ge_lb = \ _ _ -> True
+int16_add_ge_lb = \ x y -> True
int16_sub_le_ub = int16_add_ge_lb
@@ -67,11 +67,11 @@ narrow32_ge_lb = narrow8_ge_lb
narrow32_le_ub = narrow8_ge_lb
-word32_to_int32_ge = \ _ -> True
+word32_to_int32_ge = \ x -> True
-int32_to_word32_le = \ _ -> True
+int32_to_word32_le = \ x -> True
-int32_add_ge_lb = \ _ _ -> True
+int32_add_ge_lb = \ x y -> True
int32_sub_le_ub = int32_add_ge_lb
@@ -88,7 +88,7 @@ word16_and_lt = word16_lt_ub
word32_and_lt = word32_to_int32_ge
-word64_and_le = \ _ -> True
+word64_and_le = \ x -> True
int_and_ge = narrow8_ge_lb
@@ -103,11 +103,11 @@ narrow32w_lt_ub = narrow8w_lt_ub
word32_lt_ub = word32_to_int32_ge
-word32_ge_ub_false = \ _ -> False
+word32_ge_ub_false = \ x -> False
word_to_word32_lt = narrow8w_lt_ub
-word32_add_lt_ub = \ _ _ -> True
+word32_add_lt_ub = \ x y -> True
word32_sub_lt_ub = word32_add_lt_ub
=====================================
testsuite/tests/simplCore/should_compile/T26051.stderr
=====================================
@@ -7,7 +7,7 @@ Result size of Specialise = {terms: 31, types: 39, coercions: 8, joins: 0/1}
specMe [InlPrag=INLINABLE] :: forall n a. (Integral n, MaybeShowNum a n) => a -> n -> (String, n)
[LclIdX,
Arity=4,
- Unf=Unf{Src=StableUser, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [30 0 0 20] 260 10
+ Unf=Unf{Src=StableUser, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [90 60 0 20] 260 10
Tmpl= \ (@n) (@a) ($dIntegral [Occ=Once1] :: Integral n) (irred :: MaybeShowNum a n) (eta [Occ=Once1] :: a) (eta [Occ=Once1] :: n) ->
let {
$dNum :: Num n
@@ -63,7 +63,7 @@ foo = \ (x :: Int) -> specMe @Int @Bool GHC.Internal.Real.$fIntegralInt ($dCTupl
-- RHS size: {terms: 37, types: 26, coercions: 0, joins: 0/0}
main :: State# RealWorld -> (# State# RealWorld, () #)
[LclId, Arity=1, Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [0] 301 0}]
-main = \ (eta [OS=OneShot] :: State# RealWorld) -> GHC.Internal.IO.Handle.Text.hPutStr2 GHC.Internal.IO.StdHandles.stdout (case GHC.Internal.Enum.eftIntFB @(Int -> Int) (GHC.Internal.Base.mapFB @Int @(Int -> Int) @Int (\ (ds :: Int) (ds1 [OS=OneShot] :: Int -> Int) (v [OS=OneShot] :: Int) -> case v of { I# ipv -> ds1 (case ds of { I# y -> GHC.Internal.Types.I# (+# ipv y) }) }) (\ (x :: Int) -> case foo x of { (_ [Occ=Dead], y) -> y })) (breakpoint @Int) 1# 1000# (GHC.Internal.Types.I# 0#) of { I# n -> GHC.Internal.Show.itos n (GHC.Internal.Types.[] @Char) }) GHC.Internal.Types.True eta
+main = \ (eta [OS=OneShot] :: State# RealWorld) -> GHC.Internal.IO.Handle.Text.hPutStr2 GHC.Internal.IO.Handle.FD.stdout (case GHC.Internal.Enum.eftIntFB @(Int -> Int) (GHC.Internal.Base.mapFB @Int @(Int -> Int) @Int (\ (ds :: Int) (ds1 [OS=OneShot] :: Int -> Int) (v [OS=OneShot] :: Int) -> case v of { I# ipv -> ds1 (case ds of { I# y -> GHC.Internal.Types.I# (+# ipv y) }) }) (\ (x :: Int) -> case foo x of { (_ [Occ=Dead], y) -> y })) (breakpoint @Int) 1# 1000# (GHC.Internal.Types.I# 0#) of { I# n -> GHC.Internal.Show.itos n (GHC.Internal.Types.[] @Char) }) GHC.Internal.Types.True eta
-- RHS size: {terms: 1, types: 0, coercions: 3, joins: 0/0}
main :: IO ()
@@ -72,7 +72,7 @@ main = main `cast` (Sym (GHC.Internal.Types.N:IO <()>_R) :: (State# RealWorld ->
------ Local rules for imported ids --------
-"SPEC/T26051 $wspecMe @Int @Bool" [2] forall ($dIntegral :: Integral Int) (irred :: MaybeShowNum Bool Int). T26051_Import.$wspecMe @Int @Bool $dIntegral irred = $s$wspecMe
-"SPEC/T26051 specMe @Int @Bool" [2] forall ($dIntegral :: Integral Int) (irred :: MaybeShowNum Bool Int). specMe @Int @Bool $dIntegral irred = $sspecMe
+"SPEC/T26051 $wspecMe @Int @Bool" [2] forall ($dIntegral [Occ=Dead] :: Integral Int) (irred [Occ=Dead] :: MaybeShowNum Bool Int). T26051_Import.$wspecMe @Int @Bool $dIntegral irred = $s$wspecMe
+"SPEC/T26051 specMe @Int @Bool" [2] forall ($dIntegral [Occ=Dead] :: Integral Int) (irred [Occ=Dead] :: MaybeShowNum Bool Int). specMe @Int @Bool $dIntegral irred = $sspecMe
=====================================
testsuite/tests/simplCore/should_compile/T26116.stderr
=====================================
@@ -1,11 +1,11 @@
==================== Tidy Core rules ====================
"USPEC $cop1 @T @_"
- forall (@a) ($dEq :: Eq (T a)) ($dD :: D a).
+ forall (@a) ($dEq [Occ=Dead] :: Eq (T a)) ($dD :: D a).
$fCTYPEfa_$cop1 @T @a $dEq $dD
- = \ _ [Occ=Dead] -> I# 3#
+ = \ (x [Occ=Dead] :: T a) -> I# 3#
"USPEC $fCTYPEfa @T @_"
- forall (@a) ($dEq :: Eq (T a)) ($dD :: D a).
+ forall (@a) ($dEq [Occ=Dead] :: Eq (T a)) ($dD :: D a).
$fCTYPEfa @T @a $dEq $dD
= $fCTYPEfa_$s$fCTYPEfa @a $dD
=====================================
testsuite/tests/simplCore/should_compile/T8331.stderr
=====================================
@@ -1,7 +1,7 @@
==================== Tidy Core rules ====================
"SPEC $c*> @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT_$c*> @(ST s) @r $dApplicative
= ($fApplicativeReaderT2 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N).
@@ -15,7 +15,7 @@
(forall a b.
ReaderT r (ST s) a -> ReaderT r (ST s) b -> ReaderT r (ST s) b))
"SPEC $c<$ @(ST s) @_"
- forall (@s) (@r) ($dFunctor :: Functor (ST s)).
+ forall (@s) (@r) ($dFunctor [Occ=Dead] :: Functor (ST s)).
$fFunctorReaderT_$c<$ @(ST s) @r $dFunctor
= ($fApplicativeReaderT6 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N).
@@ -27,7 +27,7 @@
(forall a b. a -> ReaderT r (ST s) b -> r -> STRep s a)
(forall a b. a -> ReaderT r (ST s) b -> ReaderT r (ST s) a))
"SPEC $c<* @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT_$c<* @(ST s) @r $dApplicative
= ($fApplicativeReaderT1 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N).
@@ -41,7 +41,7 @@
(forall a b.
ReaderT r (ST s) a -> ReaderT r (ST s) b -> ReaderT r (ST s) a))
"SPEC $c<*> @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT9 @(ST s) @r $dApplicative
= ($fApplicativeReaderT4 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N).
@@ -55,11 +55,11 @@
(forall a b.
ReaderT r (ST s) (a -> b) -> ReaderT r (ST s) a -> r -> ST s b))
"SPEC $c>> @(ST s) @_"
- forall (@s) (@r) ($dMonad :: Monad (ST s)).
+ forall (@s) (@r) ($dMonad [Occ=Dead] :: Monad (ST s)).
$fMonadReaderT_$c>> @(ST s) @r $dMonad
= $fMonadAbstractIOSTReaderT_$s$c>> @s @r
"SPEC $c>>= @(ST s) @_"
- forall (@s) (@r) ($dMonad :: Monad (ST s)).
+ forall (@s) (@r) ($dMonad [Occ=Dead] :: Monad (ST s)).
$fMonadReaderT1 @(ST s) @r $dMonad
= ($fMonadAbstractIOSTReaderT2 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N).
@@ -73,7 +73,7 @@
(forall a b.
ReaderT r (ST s) a -> (a -> ReaderT r (ST s) b) -> r -> ST s b))
"SPEC $cfmap @(ST s) @_"
- forall (@s) (@r) ($dFunctor :: Functor (ST s)).
+ forall (@s) (@r) ($dFunctor [Occ=Dead] :: Functor (ST s)).
$fFunctorReaderT_$cfmap @(ST s) @r $dFunctor
= ($fApplicativeReaderT7 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N).
@@ -85,7 +85,7 @@
(forall a b. (a -> b) -> ReaderT r (ST s) a -> r -> STRep s b)
(forall a b. (a -> b) -> ReaderT r (ST s) a -> ReaderT r (ST s) b))
"SPEC $cliftA2 @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT_$cliftA2 @(ST s) @r $dApplicative
= ($fApplicativeReaderT3 @s @r)
`cast` (forall (a ::~ <*>_N) (b ::~ <*>_N) (c ::~ <*>_N).
@@ -102,15 +102,15 @@
(a -> b -> c)
-> ReaderT r (ST s) a -> ReaderT r (ST s) b -> ReaderT r (ST s) c))
"SPEC $cp1Applicative @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT_$cp1Applicative @(ST s) @r $dApplicative
= $fApplicativeReaderT_$s$fFunctorReaderT @s @r
"SPEC $cp1Monad @(ST s) @_"
- forall (@s) (@r) ($dMonad :: Monad (ST s)).
+ forall (@s) (@r) ($dMonad [Occ=Dead] :: Monad (ST s)).
$fMonadReaderT_$cp1Monad @(ST s) @r $dMonad
= $fApplicativeReaderT_$s$fApplicativeReaderT @s @r
"SPEC $cpure @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT_$cpure @(ST s) @r $dApplicative
= ($fApplicativeReaderT5 @s @r)
`cast` (forall (a ::~ <*>_N).
@@ -121,7 +121,7 @@
(forall a. a -> r -> STRep s a)
(forall a. a -> ReaderT r (ST s) a))
"SPEC $creturn @(ST s) @_"
- forall (@s) (@r) ($dMonad :: Monad (ST s)).
+ forall (@s) (@r) ($dMonad [Occ=Dead] :: Monad (ST s)).
$fMonadReaderT_$creturn @(ST s) @r $dMonad
= ($fApplicativeReaderT5 @s @r)
`cast` (forall (a ::~ <*>_N).
@@ -132,20 +132,21 @@
(forall a. a -> r -> STRep s a)
(forall a. a -> ReaderT r (ST s) a))
"SPEC $fApplicativeReaderT @(ST s) @_"
- forall (@s) (@r) ($dApplicative :: Applicative (ST s)).
+ forall (@s) (@r) ($dApplicative [Occ=Dead] :: Applicative (ST s)).
$fApplicativeReaderT @(ST s) @r $dApplicative
= $fApplicativeReaderT_$s$fApplicativeReaderT @s @r
"SPEC $fFunctorReaderT @(ST s) @_"
- forall (@s) (@r) ($dFunctor :: Functor (ST s)).
+ forall (@s) (@r) ($dFunctor [Occ=Dead] :: Functor (ST s)).
$fFunctorReaderT @(ST s) @r $dFunctor
= $fApplicativeReaderT_$s$fFunctorReaderT @s @r
"SPEC $fMonadReaderT @(ST s) @_"
- forall (@s) (@r) ($dMonad :: Monad (ST s)).
+ forall (@s) (@r) ($dMonad [Occ=Dead] :: Monad (ST s)).
$fMonadReaderT @(ST s) @r $dMonad
= $fMonadAbstractIOSTReaderT_$s$fMonadReaderT @s @r
"USPEC useAbstractMonad @(ReaderT Int (ST s))"
forall (@s)
- ($dMonadAbstractIOST :: MonadAbstractIOST (ReaderT Int (ST s))).
+ ($dMonadAbstractIOST [Occ=Dead]
+ :: MonadAbstractIOST (ReaderT Int (ST s))).
useAbstractMonad @(ReaderT Int (ST s)) $dMonadAbstractIOST
= (useAbstractMonad1 @s)
`cast` (<Int>_R
=====================================
testsuite/tests/simplCore/should_compile/T8848a.stderr
=====================================
@@ -1,6 +1,8 @@
==================== Tidy Core rules ====================
"USPEC f @[Int] @_"
- forall (@b) ($dOrd :: Ord [Int]). f @[Int] @b $dOrd = f_$sf @b
+ forall (@b) ($dOrd [Occ=Dead] :: Ord [Int]).
+ f @[Int] @b $dOrd
+ = f_$sf @b
=====================================
testsuite/tests/typecheck/should_compile/T13032.stderr
=====================================
@@ -9,7 +9,11 @@ f :: forall a b. (a ~ b) => a -> b -> Bool
Unf=Unf{Src=<vanilla>, TopLvl=True,
Value=True, ConLike=True, WorkFree=True, Expandable=True,
Guidance=ALWAYS_IF(arity=3,unsat_ok=True,boring_ok=True)}]
-f = \ (@a) (@b) _ [Occ=Dead] _ [Occ=Dead] _ [Occ=Dead] ->
+f = \ (@a)
+ (@b)
+ ($d~ [Occ=Dead] :: a ~ b)
+ (x [Occ=Dead] :: a)
+ (y [Occ=Dead] :: b) ->
GHC.Internal.Types.True
-- RHS size: {terms: 5, types: 0, coercions: 0, joins: 0/0}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e8ac16f20c85840402906bbe683aab…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e8ac16f20c85840402906bbe683aab…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 9 commits: Ensure TcM plugins are only initialised once
by Marge Bot (@marge-bot) 26 Apr '26
by Marge Bot (@marge-bot) 26 Apr '26
26 Apr '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
7a3fac92 by sheaf at 2026-04-26T18:21:20-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
03a947a5 by sheaf at 2026-04-26T18:21:25-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
0b9bbfc0 by sheaf at 2026-04-26T18:21:30-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
5d78a911 by Wen Kokke at 2026-04-26T18:21:34-04:00
rts: Add dynamic trace flags API
This commit adds an API to the RTS (exposed via Rts.h) that allows users to dynamically change the trace flags.
Prior to this commit, users were able to stop and start the profiling and heap profiling timers (via startProfTimer/stopProfTimer and startHeapProfTimer/stopHeapProfTimer).
This extends that functionality to also cover the core event types.
The getTraceFlag/setTraceFlag functions read and write the values of the trace flag cache, which is allocated by Trace.c, rather than modifying the members of RtsFlags.TraceFlags.
This is done under the assumption that the members of RtsFlags should not be modified after RTS initialisation.
Consequently, if the user modifies the trace flags using setTraceFlag, the object returned by getTraceFlags (from base) will not reflect these changes.
The trace flags are not protected by locks of any sort.
Hence, these functions are not thread-safe.
However, the trace flags are not modified by the RTS after initialisation, only read, so the race conditions introduced by one user modifying them are most likely benign.
This PR also puts the trace flag cache in a single global struct, as opposed to a collection of global variables, and changes the types of the individual flags from uint8_t to bool, as these have the same size on both Clang and GCC and are a better semantic match.
Prior to the change to uint8_t, they had type int, see 42c47cd6.
Even with its deprecation in C23, I don't think there should be any issue depending on stdbool.h.
The TRACE_X macros are redefined to access the global struct, with values cast to const bool to ensure they are read-only.
- - - - -
b756227a by Wen Kokke at 2026-04-26T18:21:34-04:00
rts: Ensure TRACE_X values are used in place of RtsFlags.TraceFlags.X
- - - - -
88895bf7 by Wen Kokke at 2026-04-26T18:21:35-04:00
rts: Fix nonmoving-GC tracing
The current nonmoving-GC tracing functions were written in a different
style from the other tracing functions. They were directly implemented
as, e.g., a traceConcMarkEnd function that called postConcMarkEnd.
The other tracing functions are implemented as, e.g., traceThreadLabel_,
a function that posts the thread label event, and traceThreadLabel, a
macro that checks whether TRACE_scheduler is set. This commit fixes that
implementation, and ensures that the nonmoving-GC tracing functions only
emit events if nonmoving-GC tracing is enabled.
- - - - -
a5b1427b by Wen Kokke at 2026-04-26T18:21:35-04:00
rts: Add SymI_HasProto for get/setTraceFlag
- - - - -
e23e0b2c by Wen Kokke at 2026-04-26T18:21:35-04:00
rts: Add SymI_HasProto for start/endEventLogging
- - - - -
1f4d2ef1 by Simon Peyton Jones at 2026-04-26T18:21:35-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
75 changed files:
- + changelog.d/hadrian-response-files.md
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI/Info.hs
- hadrian/build-cabal.bat
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/265e2fc1159f47ffc0246448e0e12a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/265e2fc1159f47ffc0246448e0e12a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 9 commits: Ensure TcM plugins are only initialised once
by Marge Bot (@marge-bot) 26 Apr '26
by Marge Bot (@marge-bot) 26 Apr '26
26 Apr '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
38638006 by sheaf at 2026-04-26T13:39:48-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
279c612c by sheaf at 2026-04-26T13:39:54-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
c6c75628 by sheaf at 2026-04-26T13:39:58-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
d500b8ae by Wen Kokke at 2026-04-26T13:40:02-04:00
rts: Add dynamic trace flags API
This commit adds an API to the RTS (exposed via Rts.h) that allows users to dynamically change the trace flags.
Prior to this commit, users were able to stop and start the profiling and heap profiling timers (via startProfTimer/stopProfTimer and startHeapProfTimer/stopHeapProfTimer).
This extends that functionality to also cover the core event types.
The getTraceFlag/setTraceFlag functions read and write the values of the trace flag cache, which is allocated by Trace.c, rather than modifying the members of RtsFlags.TraceFlags.
This is done under the assumption that the members of RtsFlags should not be modified after RTS initialisation.
Consequently, if the user modifies the trace flags using setTraceFlag, the object returned by getTraceFlags (from base) will not reflect these changes.
The trace flags are not protected by locks of any sort.
Hence, these functions are not thread-safe.
However, the trace flags are not modified by the RTS after initialisation, only read, so the race conditions introduced by one user modifying them are most likely benign.
This PR also puts the trace flag cache in a single global struct, as opposed to a collection of global variables, and changes the types of the individual flags from uint8_t to bool, as these have the same size on both Clang and GCC and are a better semantic match.
Prior to the change to uint8_t, they had type int, see 42c47cd6.
Even with its deprecation in C23, I don't think there should be any issue depending on stdbool.h.
The TRACE_X macros are redefined to access the global struct, with values cast to const bool to ensure they are read-only.
- - - - -
4975842c by Wen Kokke at 2026-04-26T13:40:03-04:00
rts: Ensure TRACE_X values are used in place of RtsFlags.TraceFlags.X
- - - - -
b4519d3b by Wen Kokke at 2026-04-26T13:40:03-04:00
rts: Fix nonmoving-GC tracing
The current nonmoving-GC tracing functions were written in a different
style from the other tracing functions. They were directly implemented
as, e.g., a traceConcMarkEnd function that called postConcMarkEnd.
The other tracing functions are implemented as, e.g., traceThreadLabel_,
a function that posts the thread label event, and traceThreadLabel, a
macro that checks whether TRACE_scheduler is set. This commit fixes that
implementation, and ensures that the nonmoving-GC tracing functions only
emit events if nonmoving-GC tracing is enabled.
- - - - -
f09f33c3 by Wen Kokke at 2026-04-26T13:40:03-04:00
rts: Add SymI_HasProto for get/setTraceFlag
- - - - -
796b5d0f by Wen Kokke at 2026-04-26T13:40:03-04:00
rts: Add SymI_HasProto for start/endEventLogging
- - - - -
265e2fc1 by Simon Peyton Jones at 2026-04-26T13:40:03-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
75 changed files:
- + changelog.d/hadrian-response-files.md
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI/Info.hs
- hadrian/build-cabal.bat
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ef3c7a8a2917671461be1374b5fafc…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/ef3c7a8a2917671461be1374b5fafc…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 9 commits: Ensure TcM plugins are only initialised once
by Marge Bot (@marge-bot) 26 Apr '26
by Marge Bot (@marge-bot) 26 Apr '26
26 Apr '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
667b9ec8 by sheaf at 2026-04-26T08:06:39-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
816814f5 by sheaf at 2026-04-26T08:06:45-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
7898261d by sheaf at 2026-04-26T08:06:50-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
b35dc3ef by Wen Kokke at 2026-04-26T08:06:53-04:00
rts: Add dynamic trace flags API
This commit adds an API to the RTS (exposed via Rts.h) that allows users to dynamically change the trace flags.
Prior to this commit, users were able to stop and start the profiling and heap profiling timers (via startProfTimer/stopProfTimer and startHeapProfTimer/stopHeapProfTimer).
This extends that functionality to also cover the core event types.
The getTraceFlag/setTraceFlag functions read and write the values of the trace flag cache, which is allocated by Trace.c, rather than modifying the members of RtsFlags.TraceFlags.
This is done under the assumption that the members of RtsFlags should not be modified after RTS initialisation.
Consequently, if the user modifies the trace flags using setTraceFlag, the object returned by getTraceFlags (from base) will not reflect these changes.
The trace flags are not protected by locks of any sort.
Hence, these functions are not thread-safe.
However, the trace flags are not modified by the RTS after initialisation, only read, so the race conditions introduced by one user modifying them are most likely benign.
This PR also puts the trace flag cache in a single global struct, as opposed to a collection of global variables, and changes the types of the individual flags from uint8_t to bool, as these have the same size on both Clang and GCC and are a better semantic match.
Prior to the change to uint8_t, they had type int, see 42c47cd6.
Even with its deprecation in C23, I don't think there should be any issue depending on stdbool.h.
The TRACE_X macros are redefined to access the global struct, with values cast to const bool to ensure they are read-only.
- - - - -
96010922 by Wen Kokke at 2026-04-26T08:06:54-04:00
rts: Ensure TRACE_X values are used in place of RtsFlags.TraceFlags.X
- - - - -
8ce4b604 by Wen Kokke at 2026-04-26T08:06:54-04:00
rts: Fix nonmoving-GC tracing
The current nonmoving-GC tracing functions were written in a different
style from the other tracing functions. They were directly implemented
as, e.g., a traceConcMarkEnd function that called postConcMarkEnd.
The other tracing functions are implemented as, e.g., traceThreadLabel_,
a function that posts the thread label event, and traceThreadLabel, a
macro that checks whether TRACE_scheduler is set. This commit fixes that
implementation, and ensures that the nonmoving-GC tracing functions only
emit events if nonmoving-GC tracing is enabled.
- - - - -
1b91ce9f by Wen Kokke at 2026-04-26T08:06:54-04:00
rts: Add SymI_HasProto for get/setTraceFlag
- - - - -
e2eb47fe by Wen Kokke at 2026-04-26T08:06:54-04:00
rts: Add SymI_HasProto for start/endEventLogging
- - - - -
ef3c7a8a by Simon Peyton Jones at 2026-04-26T08:06:55-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
75 changed files:
- + changelog.d/hadrian-response-files.md
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI/Info.hs
- hadrian/build-cabal.bat
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cc042a47be9bc2d546dc424e8b112f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cc042a47be9bc2d546dc424e8b112f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/supersven/interpreter-flags] ghc: Distinguish between having an interpreter and having an internal one
by Sven Tennie (@supersven) 26 Apr '26
by Sven Tennie (@supersven) 26 Apr '26
26 Apr '26
Sven Tennie pushed to branch wip/supersven/interpreter-flags at Glasgow Haskell Compiler / GHC
Commits:
9efefc8c by Sven Tennie at 2026-04-26T13:11:24+02:00
ghc: Distinguish between having an interpreter and having an internal one
Actually, these are related but different things:
- ghc can run an interpreter (either internal or external)
- ghc is compiled with an internal interpreter
Splitting the logic solves compiler warnings and expresses the intent
better.
- - - - -
6 changed files:
- + changelog.d/T19174.md
- ghc/GHC/Driver/Session/Mode.hs
- ghc/GHCi/UI.hs
- ghc/Main.hs
- ghc/ghc-bin.cabal.in
- hadrian/src/Settings/Packages.hs
Changes:
=====================================
changelog.d/T19174.md
=====================================
@@ -0,0 +1,17 @@
+section: compiler
+issues: #19174
+mrs: !15714
+synopsis:
+ Introduce HAVE_INTERPRETER flag separate from HAVE_INTERNAL_INTERPRETER
+description:
+ GHC now distinguishes between having any interpreter support (internal or
+ external) via the `HAVE_INTERPRETER` CPP flag, and having specifically
+ an internal interpreter via `HAVE_INTERNAL_INTERPRETER`. The `ghc-bin`
+ package now has separate `interpreter` and `internal-interpreter` cabal
+ flags. Interactive mode and GHCi UI features now check `HAVE_INTERPRETER`
+ instead of `HAVE_INTERNAL_INTERPRETER`, while internal interpreter-specific
+ code (like the directory change handler in GHCi) remains guarded by
+ `HAVE_INTERNAL_INTERPRETER`. In cross-compilation builds, the
+ `internal-interpreter` flag is disabled while the `interpreter` flag can
+ still be enabled for external interpreter support.
+ This does not change current behaviour, but prevents compiler warnings.
=====================================
ghc/GHC/Driver/Session/Mode.hs
=====================================
@@ -132,7 +132,7 @@ isDoEvalMode :: Mode -> Bool
isDoEvalMode (Right (Right (DoEval _))) = True
isDoEvalMode _ = False
-#if defined(HAVE_INTERNAL_INTERPRETER)
+#if defined(HAVE_INTERPRETER)
isInteractiveMode :: PostLoadMode -> Bool
isInteractiveMode DoInteractive = True
isInteractiveMode _ = False
=====================================
ghc/GHCi/UI.hs
=====================================
@@ -1909,7 +1909,9 @@ changeDirectory dir = do
fhv <- compileGHCiExpr $
"System.Directory.setCurrentDirectory " ++ show dir'
liftIO $ evalIO interp fhv
+#if defined(HAVE_INTERNAL_INTERPRETER)
_ -> pure ()
+#endif
trySuccess :: GhciMonad m => m SuccessFlag -> m SuccessFlag
trySuccess act =
=====================================
ghc/Main.hs
=====================================
@@ -36,7 +36,7 @@ import GHC.Driver.Config.Diagnostic
import GHC.Platform
import GHC.Platform.Host
-#if defined(HAVE_INTERNAL_INTERPRETER)
+#if defined(HAVE_INTERPRETER)
import GHCi.UI ( interactiveUI, ghciWelcomeMsg, defaultGhciSettings, languageEditionMsg )
#endif
@@ -288,7 +288,7 @@ doRun units srcs args = do
args' = drop 1 $ dropWhile (/= "--") $ map unLoc args
ghciUI :: [String] -> [(FilePath, Maybe Phase)] -> Maybe [String] -> Ghc ()
-#if !defined(HAVE_INTERNAL_INTERPRETER)
+#if !defined(HAVE_INTERPRETER)
ghciUI _ _ _ =
throwGhcException (CmdLineError "not built for interactive use")
#else
@@ -332,7 +332,7 @@ showBanner :: PostLoadMode -> DynFlags -> IO ()
showBanner _postLoadMode dflags = do
let verb = verbosity dflags
-#if defined(HAVE_INTERNAL_INTERPRETER)
+#if defined(HAVE_INTERPRETER)
-- Show the GHCi banner
when (isInteractiveMode _postLoadMode && verb >= 1) $
do putStrLn ghciWelcomeMsg
=====================================
ghc/ghc-bin.cabal.in
=====================================
@@ -22,6 +22,11 @@ Flag internal-interpreter
Default: False
Manual: True
+Flag interpreter
+ Description: Build with interpreter support, both internal and external.
+ Default: False
+ Manual: True
+
Flag threaded
Description: Link the ghc executable against the threaded RTS
Default: True
@@ -56,7 +61,7 @@ Executable ghc
-rtsopts=all
"-with-rtsopts=-K512M -H -I5 -T"
- if flag(internal-interpreter)
+ if flag(interpreter)
-- NB: this is never built by the bootstrapping GHC+libraries
Build-depends:
deepseq >= 1.4 && < 1.6,
@@ -65,7 +70,7 @@ Executable ghc
haskeline == 0.8.*,
exceptions == 0.10.*,
time >= 1.8 && < 1.16
- CPP-Options: -DHAVE_INTERNAL_INTERPRETER
+ CPP-Options: -DHAVE_INTERPRETER
Other-Modules:
GHCi.Leak
GHCi.UI
@@ -82,6 +87,9 @@ Executable ghc
UnboxedTuples
ViewPatterns
+ if flag(internal-interpreter)
+ CPP-Options: -DHAVE_INTERNAL_INTERPRETER
+
if flag(threaded)
ghc-options: -threaded
=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -114,7 +114,8 @@ packageArgs = do
, compilerStageOption ghcDebugAssertions ? arg "-DDEBUG" ]
, builder (Cabal Flags) ? mconcat
- [ (expr (ghcWithInterpreter stage)) `cabalFlag` "internal-interpreter"
+ [ expr (ghcWithInterpreter stage) `cabalFlag` "interpreter"
+ , andM [expr (ghcWithInterpreter stage), notCross] `cabalFlag` "internal-interpreter"
, ifM stage0
-- We build a threaded stage 1 if the bootstrapping compiler
-- supports it.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9efefc8c446eff2553330d563945b13…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9efefc8c446eff2553330d563945b13…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/fendor/hpc-bc-support] 11 commits: Revert use of generic instances for compiler time perf reasons.
by Hannes Siebenhandl (@fendor) 26 Apr '26
by Hannes Siebenhandl (@fendor) 26 Apr '26
26 Apr '26
Hannes Siebenhandl pushed to branch wip/fendor/hpc-bc-support at Glasgow Haskell Compiler / GHC
Commits:
86a646a6 by Andreas Klebinger at 2026-04-22T13:00:05-04:00
Revert use of generic instances for compiler time perf reasons.
Revert "Derive Semigroup/Monoid for instances believed could be derived in #25871"
This reverts commit 11a04cbb221cc404fe00d65d7c951558ede4caa9.
Revert "add Ghc.Data.Pair deriving"
This reverts commit 15d9ce449e1be8c01b89fd39bdf1e700ea7d1dce.
- - - - -
bc9ee1cf by Wen Kokke at 2026-04-22T13:00:51-04:00
hadrian: Fix docs to remove static flavour
In 638f6548, the static flavour was turned into into the fully_static
flavour transformer. However, this commit did not update flavours.md.
- - - - -
cc9cc6d5 by Cheng Shao at 2026-04-23T09:40:46+00:00
configure: bump LlvmMaxVersion to 23
This patch bumps `LlvmMaxVersion` to 23 to support LLVM 22.x releases.
- - - - -
2ea7ef8e by Cheng Shao at 2026-04-23T09:46:26+00:00
changelog: add llvm 22.x support
- - - - -
5574ee10 by Cheng Shao at 2026-04-24T08:24:30-04:00
compiler: avoid unused temporary `appendFS` operands
This patch fixes unused temporary `appendFS` operands in the codebase
that are retained in the `FastString` table after concatenation.
Rewrite rules are added so that if an operand is
`fsLit`/`mkFastString`, the `appendFS` application is rewritten to
append the `ShortByteString` operands first. The patch also fixes
`sconcat` behavior to align with `mconcat` for the same reason. Fixes #27205.
- - - - -
4ed78760 by mangoiv at 2026-04-24T08:25:13-04:00
contributing: adjust MR template to be less verbose
- MR template only shows text that is relevant for submissiong
- MR template was rewritten so it's readable from a user's and reviewer's
perspective
Resolves #27165
Co-Authored-By: @sheaf
- - - - -
87db83e2 by Cheng Shao at 2026-04-24T14:37:21-04:00
ci: bump freebsd boot ghc to 9.10.3
This commit bumps freebsd boot ghc to 9.10.3 to align with other
platforms and prevent outdated boot libs in boot ghc to block the
freebsd job.
- - - - -
17e3a0b7 by Cheng Shao at 2026-04-24T14:37:21-04:00
compiler: improve Binary instance of Array
This patch improves the `Binary` instance of `Array`:
- We no longer allocate intermediate lists. When serializing an
`Array`, we iterate over the elements directly; when deserializing
it, we allocate the result `Array` and fill it in a loop.
- Now we only serialize the array bounds tuple; the length field is
not needed.
Closes #27109.
- - - - -
2d30f7d3 by sheaf at 2026-04-24T14:38:23-04:00
Vendor mini-QuickCheck for testsuite
This commit extracts the vendored QuickCheck implementation from the
foundation testsuite to make it more broadly available in the GHC
testsuite, and makes use of it in the simd006 test (which also used
a vendored QuickCheck implementation).
On the way, we update the linear congruential generator to avoid the
shortcoming of only generating 31 bit large numbers.
Fixes #25990 and #25969.
- - - - -
ef41cde7 by fendor at 2026-04-26T11:23:51+02:00
Expose startupHpc as an rts symbol
- - - - -
bb1cc992 by fendor at 2026-04-26T11:23:52+02:00
Make HPC work with bytecode interpreter
Add support to generate .tix files from bytecode objects and the
bytecode interpreter.
Conceptually, we insert HPC ticks into the bytecode similar to how we insert
breakpoints.
HPC and breakpoints do not share the same tick array but we use a separate
tick-array for hpc/breakpoint ticks during bytecode generation.
We teach the bytecode interpreter to handle hpc ticks.
The implementation is quite trivial, simply increment the counter in the
global hpc_ticks array for the respective module.
This hpc_ticks array is generated as part of the `CStub`, so we can rely
on it existing.
A tricky bit is "registering" a bytecode object for HPC instrumentation.
In the compiled case, this is achieved via CStub and initializer/finalizers
`.init` sections which are called when the executable is run.
After the initializers have been invoked, which is before `hs_init_ghc`,
we then call `startup_hpc` in `hs_init_ghc` iff any modules were "registered"
for hpc instrumentation via `hs_hpc_module`.
Since bytecode objects are loaded after starting up GHCi, this workflow
doesn't work for supporting `hpc` and the `hpc` run-time is never
started, even if a module is added for instrumentation.
We fix this issue by employing the same technique as is for `SptEntry`s:
* We introduce a new field to `CompiledByteCode`, called `ByteCodeHpcInfo`
which contains enough information to call `hs_hpc_module`, allowing us to
register the module for `hpc` instrumentation`.
* After registering the module, we unconditionally call `startupHpc`, to make
sure the .tix file is written.
Calling `startupHpc` multiple times is safe.
Calling `hs_hpc_module` multiple times for the same module is also safe.
If we didn't register the hpc module in this way, evaluating a bytecode object
instrumented with `-fhpc` without registering it in the `hpc` run-time will
simply not generate any `.tix` files for this bytecode object.
However, this shouldn't happen if everything is set up correctly.
Closes #27036
- - - - -
78 changed files:
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .gitlab/merge_request_templates/Default.md
- + changelog.d/binary-array-no-list
- + changelog.d/bytecode-interpreter-hpc-support
- + changelog.d/llvm-22
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Binary.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/CmmToAsm/X86/CodeGen.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Data/FastString.hs
- compiler/GHC/Data/Pair.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/CodeOutput.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Coverage.hs
- compiler/GHC/HsToCore/Pmc.hs
- compiler/GHC/HsToCore/Pmc/Solver/Types.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Types/HpcInfo.hs
- compiler/GHC/Types/Unique/DSet.hs
- compiler/GHC/Unit/Module/ModGuts.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Ppr/Colour.hs
- configure.ac
- hadrian/doc/flavours.md
- + libraries/ghci/GHCi/Coverage.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- libraries/ghci/ghci.cabal.in
- rts/Disassembler.c
- rts/Hpc.c
- rts/Interpreter.c
- rts/RtsSymbols.c
- rts/include/rts/Bytecodes.h
- testsuite/driver/testlib.py
- + testsuite/tests/MiniQuickCheck.hs
- testsuite/tests/hpc/Makefile
- testsuite/tests/hpc/T17073.stdout → testsuite/tests/hpc/T17073a.stdout
- + testsuite/tests/hpc/T17073b.stdout
- testsuite/tests/hpc/T20568.stdout → testsuite/tests/hpc/T20568a.stdout
- + testsuite/tests/hpc/T20568b.stdout
- testsuite/tests/hpc/all.T
- testsuite/tests/hpc/fork/Makefile
- testsuite/tests/hpc/function/Makefile
- testsuite/tests/hpc/function/test.T
- + testsuite/tests/hpc/function/tough1.stderr
- + testsuite/tests/hpc/function/tough1.stdout
- testsuite/tests/hpc/function2/test.T
- + testsuite/tests/hpc/function2/tough3.script
- + testsuite/tests/hpc/ghc_ghci/BytecodeMain.hs
- testsuite/tests/hpc/ghc_ghci/Makefile
- + testsuite/tests/hpc/ghc_ghci/hpc_ghc_ghci_bytecode.stdout
- + testsuite/tests/hpc/ghc_ghci/hpc_ghci01.stdout
- + testsuite/tests/hpc/ghc_ghci/hpc_ghci02.stdout
- testsuite/tests/hpc/ghc_ghci/test.T
- testsuite/tests/hpc/simple/Makefile
- + testsuite/tests/hpc/simple/hpc002.hs
- + testsuite/tests/hpc/simple/hpc002.stdout
- + testsuite/tests/hpc/simple/hpc003.hs
- + testsuite/tests/hpc/simple/hpc003.script
- + testsuite/tests/hpc/simple/hpc003.stdout
- testsuite/tests/hpc/simple/test.T
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/numeric/should_run/foundation.hs
- testsuite/tests/simd/should_run/all.T
- testsuite/tests/simd/should_run/simd006.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6447e5e0eb1f6de85c40c1e51c4dd5…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/6447e5e0eb1f6de85c40c1e51c4dd5…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 9 commits: Ensure TcM plugins are only initialised once
by Marge Bot (@marge-bot) 26 Apr '26
by Marge Bot (@marge-bot) 26 Apr '26
26 Apr '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
c1ec2bad by sheaf at 2026-04-26T05:15:13-04:00
Ensure TcM plugins are only initialised once
This commit ensures we keep TcM plugins (typechecker plugins,
defaulting plugins and hole fit plugins) running all the way through
desugaring, instead of stopping them at the end of typechecking.
To do this, the "stop" actions of TcPlugin and DefaultingPlugin are
split into two: one for the "post-typecheck" action, and one for the
final shutdown action (after desugaring).
This allows the plugins to be invoked by the pattern match checker
(during desugaring) without having to be repeatedly re-initialised and
stopped, fixing #26839.
In the process, this commit modifies 'initTc' and 'initTcInteractive',
adding an extra argument that describes whether to start/stop the 'TcM'
plugins.
See Note [Stop TcM plugins after desugaring] for an overview.
- - - - -
c44634a1 by sheaf at 2026-04-26T05:15:18-04:00
Hadrian: add --keep-response-files
This commit adds a Hadrian flag that allows response files to be
retained. This is useful for debugging a failing Hadrian command line.
- - - - -
428c78aa by sheaf at 2026-04-26T05:15:24-04:00
hadrian/build-cabal.bat: fix build on Windows
Commit 8cb99552f6 introduced a warning for a missing package index.
However, the logic was faulty on Windows: the piping was broken, and
"remote-repo-cache:" was being interpreted as a (malformed) drive letter,
leading to the error:
The filename, directory name, or volume label syntax is incorrect.
This commit fixes that by using a temporary file instead of piping.
- - - - -
508777dd by Wen Kokke at 2026-04-26T05:15:27-04:00
rts: Add dynamic trace flags API
This commit adds an API to the RTS (exposed via Rts.h) that allows users to dynamically change the trace flags.
Prior to this commit, users were able to stop and start the profiling and heap profiling timers (via startProfTimer/stopProfTimer and startHeapProfTimer/stopHeapProfTimer).
This extends that functionality to also cover the core event types.
The getTraceFlag/setTraceFlag functions read and write the values of the trace flag cache, which is allocated by Trace.c, rather than modifying the members of RtsFlags.TraceFlags.
This is done under the assumption that the members of RtsFlags should not be modified after RTS initialisation.
Consequently, if the user modifies the trace flags using setTraceFlag, the object returned by getTraceFlags (from base) will not reflect these changes.
The trace flags are not protected by locks of any sort.
Hence, these functions are not thread-safe.
However, the trace flags are not modified by the RTS after initialisation, only read, so the race conditions introduced by one user modifying them are most likely benign.
This PR also puts the trace flag cache in a single global struct, as opposed to a collection of global variables, and changes the types of the individual flags from uint8_t to bool, as these have the same size on both Clang and GCC and are a better semantic match.
Prior to the change to uint8_t, they had type int, see 42c47cd6.
Even with its deprecation in C23, I don't think there should be any issue depending on stdbool.h.
The TRACE_X macros are redefined to access the global struct, with values cast to const bool to ensure they are read-only.
- - - - -
e521360d by Wen Kokke at 2026-04-26T05:15:28-04:00
rts: Ensure TRACE_X values are used in place of RtsFlags.TraceFlags.X
- - - - -
aeb2e8e6 by Wen Kokke at 2026-04-26T05:15:28-04:00
rts: Fix nonmoving-GC tracing
The current nonmoving-GC tracing functions were written in a different
style from the other tracing functions. They were directly implemented
as, e.g., a traceConcMarkEnd function that called postConcMarkEnd.
The other tracing functions are implemented as, e.g., traceThreadLabel_,
a function that posts the thread label event, and traceThreadLabel, a
macro that checks whether TRACE_scheduler is set. This commit fixes that
implementation, and ensures that the nonmoving-GC tracing functions only
emit events if nonmoving-GC tracing is enabled.
- - - - -
394d2f1e by Wen Kokke at 2026-04-26T05:15:28-04:00
rts: Add SymI_HasProto for get/setTraceFlag
- - - - -
125e2926 by Wen Kokke at 2026-04-26T05:15:28-04:00
rts: Add SymI_HasProto for start/endEventLogging
- - - - -
cc042a47 by Simon Peyton Jones at 2026-04-26T05:15:28-04:00
Fix assertion check in checkResultTy
As #27210 shows, the assertion was a little bit too eager.
I refactored a bit by moving some code from GHC.Tc.Gen.App
to GHC.Tc.Utils.Unify; see the new function tcSubTypeApp,
which replaces tcSubTypeDS
- - - - -
75 changed files:
- + changelog.d/hadrian-response-files.md
- + changelog.d/tcplugin_init.md
- + changelog.d/tcplugins-pmc.md
- + changelog.d/typecheckModule-API.md
- + changelog.d/withTcPlugins.md
- compiler/GHC.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Pipeline/Monad.hs
- compiler/GHC/Driver/Pipeline/Phases.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Heap/Inspect.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Errors/Hole.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI/Info.hs
- hadrian/build-cabal.bat
- hadrian/src/Builder.hs
- hadrian/src/CommandLine.hs
- hadrian/src/Hadrian/Builder/Ar.hs
- hadrian/src/Hadrian/Utilities.hs
- rts/RtsSymbols.c
- rts/Trace.c
- rts/Trace.h
- rts/include/rts/EventLogWriter.h
- rts/sm/NonMoving.c
- testsuite/tests/ghc-api/T26910.hs
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghci/should_run/tc-plugin-ghci/TcPluginGHCi.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInterference.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultInvalid.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/plugins/defaulting-plugin/DefaultMultiParam.hs
- testsuite/tests/plugins/echo-plugin/Echo.hs
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/tcplugins/Common.hs
- testsuite/tests/tcplugins/RewritePerfPlugin.hs
- testsuite/tests/tcplugins/T11462_Plugin.hs
- testsuite/tests/tcplugins/T11525_Plugin.hs
- testsuite/tests/tcplugins/T26395_Plugin.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.script
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Ghci.stdout
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.hs-boot
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode.stderr
- + testsuite/tests/tcplugins/TcPlugin_InitStop_NoCode_aux.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.hs
- + testsuite/tests/tcplugins/TcPlugin_InitStop_Warn.stderr
- testsuite/tests/tcplugins/all.T
- + testsuite/tests/tcplugins/tc-plugin-initstop/Makefile
- + testsuite/tests/tcplugins/tc-plugin-initstop/Setup.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/TcPlugin_InitStop_Plugin.hs
- + testsuite/tests/tcplugins/tc-plugin-initstop/tc-plugin-initstop.cabal
- + testsuite/tests/typecheck/should_fail/T27210.hs
- + testsuite/tests/typecheck/should_fail/T27210.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/wasm/should_run/control-flow/LoadCmmGroup.hs
- utils/haddock/haddock-api/src/Haddock/Interface/AttachInstances.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2b6424fcd5e8a2d82dd8cf520a6e86…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2b6424fcd5e8a2d82dd8cf520a6e86…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26989] Refactor the Simplifier's handling of DupFlag
by Simon Peyton Jones (@simonpj) 26 Apr '26
by Simon Peyton Jones (@simonpj) 26 Apr '26
26 Apr '26
Simon Peyton Jones pushed to branch wip/T26989 at Glasgow Haskell Compiler / GHC
Commits:
e8ac16f2 by Simon Peyton Jones at 2026-04-26T01:17:47+01:00
Refactor the Simplifier's handling of DupFlag
...and how it deals with re-simplification of argumnets
- - - - -
3 changed files:
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
Changes:
=====================================
compiler/GHC/Core/Opt/Simplify/Env.hs
=====================================
@@ -442,7 +442,7 @@ instance Outputable SimplFloats where
, text "joins:" <+> ppr jf
, text "in_scope:" <+> ppr is ])
-emptyFloats :: SimplEnv -> SimplFloats
+emptyFloats :: SimplEnvIS -> SimplFloats
emptyFloats env
= SimplFloats { sfLetFloats = emptyLetFloats
, sfJoinFloats = emptyJoinFloats
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -283,7 +283,7 @@ simplRecOrTopPair :: SimplEnv
simplRecOrTopPair env bind_cxt old_bndr new_bndr rhs
| Just env' <- preInlineUnconditionally env (bindContextLevel bind_cxt)
- old_bndr NoDup rhs env
+ old_bndr rhs (UnSimplified env)
= {-#SCC "simplRecOrTopPair-pre-inline-uncond" #-}
simplTrace "SimplBindr:inline-uncond1" (ppr old_bndr) $
do { tick (PreInlineUnconditionally old_bndr)
@@ -386,10 +386,9 @@ simplJoinBind is_rec cont (old_bndr, unf_se) (new_bndr, env) (rhs, rhs_se)
; completeBind (BC_Join is_rec cont) (old_bndr, unf_se) (new_bndr, rhs', env) }
--------------------------
-simplAuxBind :: String
- -> SimplEnv
- -> InId -- Old binder; not a JoinId
- -> OutExpr -- Simplified RHS
+simplAuxBind :: (SimplAltFlag, SimplEnv)
+ -> Id -- Binder; not a JoinId
+ -> OutExpr -- Simplified RHS
-> SimplM (SimplFloats, SimplEnv)
-- A specialised variant of completeBindX used to construct non-recursive
-- auxiliary bindings, notably in knownCon.
@@ -399,7 +398,7 @@ simplAuxBind :: String
--
-- Precondition: rhs satisfies the let-can-float invariant
-simplAuxBind _str env bndr new_rhs
+simplAuxBind (saf,env) bndr new_rhs
| assertPpr (isId bndr && not (isJoinId bndr)) (ppr bndr) $
isDeadBinder bndr -- Not uncommon; e.g. case (a,b) of c { (p,q) -> p }
= return (emptyFloats env, env) -- Here c is dead, and we avoid
@@ -428,13 +427,14 @@ simplAuxBind _str env bndr new_rhs
; let rhs_floats = emptyFloats env `addLetFloats` anf_floats
-- Simplify the binder and complete the binding
- ; (env1, new_bndr) <- simplBinder (env `setInScopeFromF` rhs_floats) bndr
+ ; (env1, new_bndr) <- simplAltIdBinder (saf, env `setInScopeFromF` rhs_floats) bndr
; (bind_float, env2) <- completeBind (BC_Let NotTopLevel NonRecursive)
- (bndr,env) (new_bndr, rhs1, env1)
+ (bndr, env) (new_bndr, rhs1, env1)
; return (rhs_floats `addFloats` bind_float, env2) }
+
{- *********************************************************************
* *
Cast worker/wrapper
@@ -772,7 +772,7 @@ That's what the 'go' loop in prepareRhs does
-}
prepareRhs :: HasDebugCallStack
- => SimplEnv -> TopLevelFlag
+ => SimplEnvIS -> TopLevelFlag
-> FastString -- Base for any new variables
-> OutExpr
-> SimplM (LetFloats, OutExpr)
@@ -832,7 +832,8 @@ prepareRhs env top_lvl occ rhs0
anfise other = return (emptyLetFloats, other)
-makeTrivialArg :: HasDebugCallStack => SimplEnv -> ArgSpec -> SimplM (LetFloats, ArgSpec)
+makeTrivialArg :: HasDebugCallStack => SimplEnvIS -> ArgSpec
+ -> SimplM (LetFloats, ArgSpec)
makeTrivialArg env arg@(ValArg { as_arg = e, as_dmd = dmd })
= do { (floats, e') <- makeTrivial env NotTopLevel dmd (fsLit "arg") e
; return (floats, arg { as_arg = e' }) }
@@ -840,7 +841,7 @@ makeTrivialArg _ arg@(TyArg {})
= return (emptyLetFloats, arg)
makeTrivial :: HasDebugCallStack
- => SimplEnv -> TopLevelFlag -> Demand
+ => SimplEnvIS -> TopLevelFlag -> Demand
-> FastString -- ^ A "friendly name" to build the new binder from
-> OutExpr
-> SimplM (LetFloats, OutExpr)
@@ -1260,9 +1261,9 @@ simplExprF1 env (App fun arg) cont
-- observed the quadratic behavior, so this extra entanglement
-- seems not worthwhile.
simplExprF env fun $
- ApplyToVal { sc_arg = arg, sc_env = env
+ ApplyToVal { sc_arg = arg, sc_env = UnSimplified env
, sc_hole_ty = substTy env (exprType fun)
- , sc_dup = NoDup, sc_cont = cont }
+ , sc_cont = cont }
simplExprF1 env expr@(Lam {}) cont
= {-#SCC "simplExprF1-Lam" #-}
@@ -1280,9 +1281,8 @@ simplExprF1 env expr@(Lam {}) cont
simplExprF1 env (Case scrut bndr _ alts) cont
= {-#SCC "simplExprF1-Case" #-}
- simplExprF env scrut (Select { sc_dup = NoDup, sc_bndr = bndr
- , sc_alts = alts
- , sc_env = env, sc_cont = cont })
+ simplExprF env scrut (Select { sc_bndr = bndr, sc_alts = alts
+ , sc_env = UnSimplified env, sc_cont = cont })
simplExprF1 env (Let (Rec pairs) body) cont
| Just pairs' <- joinPointBindings_maybe pairs
@@ -1298,7 +1298,7 @@ simplExprF1 env (Let (NonRec bndr rhs) body) cont
do { ty' <- simplType env ty
; simplExprF (extendTvSubst env bndr ty') body cont }
- | Just env' <- preInlineUnconditionally env NotTopLevel bndr NoDup rhs env
+ | Just env' <- preInlineUnconditionally env NotTopLevel bndr rhs (UnSimplified env)
-- Because of the let-can-float invariant, it's ok to
-- inline freely, or to drop the binding if it is dead.
= do { simplTrace "SimplBindr:inline-uncond2" (ppr bndr) $
@@ -1570,7 +1570,8 @@ simplTick env tickish expr cont
rebuild :: SimplEnv -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
rebuild env expr cont = rebuild_go (zapSubstEnv env) expr cont
-rebuild_go :: SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
+rebuild_go :: HasDebugCallStack
+ => SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
-- SimplEnvIS: at this point the substitution in the SimplEnv is irrelevant;
-- only the in-scope set matters, plus the flags.
rebuild_go env expr cont
@@ -1589,22 +1590,26 @@ rebuild_go env expr cont
co' = optOutCoercion env co opt
Select { sc_bndr = bndr, sc_alts = alts, sc_env = se, sc_cont = cont }
- -> rebuildCase (se `setInScopeFromE` env) expr bndr alts cont
+ -> rebuildCase (mkAltEnv env se) expr bndr alts cont
StrictArg { sc_fun = fun, sc_cont = cont, sc_fun_ty = fun_ty }
-> rebuildCall env (addValArgTo fun expr fun_ty) cont
StrictBind { sc_bndr = b, sc_body = body, sc_env = se
, sc_cont = cont, sc_from = from_what }
- -> completeBindX (se `setInScopeFromE` env) from_what b expr body cont
+ -> completeBindX body_env from_what b expr body cont
+ where
+ (_saf, body_env) = mkAltEnv env se
+ -- In the Simplified case, it's always a OkDup, so we accept that
+ -- `completeBindX` may re-simplify `body`
ApplyToTy { sc_arg_ty = ty, sc_cont = cont}
-> rebuild_go env (App expr (Type ty)) cont
- ApplyToVal { sc_arg = arg, sc_env = se, sc_dup = dup_flag
+ ApplyToVal { sc_arg = arg, sc_env = se
, sc_cont = cont, sc_hole_ty = fun_ty }
-- See Note [Avoid redundant simplification]
- -> do { (_, _, arg') <- simplLazyArg env dup_flag fun_ty Nothing se arg
+ -> do { (_, arg') <- simplArg env fun_ty Nothing se arg
; rebuild_go env (App expr arg') cont }
completeBindX :: SimplEnv
@@ -1748,7 +1753,7 @@ pushCast env co cont
-- co1 :: t1 ~ s1
-- co2 :: s2 ~ t2
go co co_is_opt cont@(ApplyToVal { sc_arg = arg, sc_env = arg_se
- , sc_dup = dup, sc_cont = tail
+ , sc_cont = tail
, sc_hole_ty = fun_ty })
| not co_is_opt
= -- pushCoValArg duplicates the coercion, so optimise first
@@ -1763,7 +1768,7 @@ pushCast env co cont
-- See Note [Avoiding simplifying repeatedly]
MCo co1 ->
- do { (dup', arg_se', arg') <- simplLazyArg env dup fun_ty Nothing arg_se arg
+ do { (arg_se', arg') <- simplArg env fun_ty Nothing arg_se arg
-- When we build the ApplyTo we can't mix the OutCoercion
-- 'co' with the InExpr 'arg', so we simplify
-- to make it all consistent. It's a bit messy.
@@ -1771,7 +1776,6 @@ pushCast env co cont
-- Example of use: #995
; return (ApplyToVal { sc_arg = mkCast arg' co1
, sc_env = arg_se'
- , sc_dup = dup'
, sc_cont = tail'
, sc_hole_ty = coercionLKind co }) } } }
@@ -1788,26 +1792,24 @@ pushCast env co cont
go_mco MRefl _ cont = return cont
go_mco (MCo co) opt cont = go co opt cont
-simplLazyArg :: SimplEnvIS -- ^ Used only for its InScopeSet
- -> DupFlag
- -> OutType -- ^ Type of the function applied to this arg
- -> Maybe ArgInfo -- ^ Just <=> This arg `ai` occurs in an app
- -- `f a1 ... an` where we have ArgInfo on
- -- how `f` uses `ai`, affecting the Stop
- -- continuation passed to 'simplExprC'
- -> StaticEnv -> CoreExpr -- ^ Expression with its static envt
- -> SimplM (DupFlag, StaticEnv, OutExpr)
-simplLazyArg env dup_flag fun_ty mb_arg_info arg_env arg
- | isSimplified dup_flag
- = return (dup_flag, arg_env, arg)
- | otherwise
- = do { let arg_env' = arg_env `setInScopeFromE` env
- ; let arg_ty = funArgTy fun_ty
- ; let stop = case mb_arg_info of
+simplArg :: SimplEnvIS -- ^ Used only for its InScopeSet
+ -> OutType -- ^ Type of the function applied to this arg
+ -> Maybe ArgInfo -- ^ Just <=> This arg `ai` occurs in an app
+ -- `f a1 ... an` where we have ArgInfo on
+ -- how `f` uses `ai`, affecting the Stop
+ -- continuation passed to 'simplExprC'
+ -> StaticEnv -> CoreExpr -- ^ Expression with its static envt
+ -> SimplM (StaticEnv, OutExpr)
+simplArg _ _ _ se@(Simplified {}) arg
+ = return (se, arg)
+simplArg env fun_ty mb_arg_info (UnSimplified arg_se) arg
+ = do { let arg_env' = arg_se `setInScopeFromE` env
+ arg_ty = funArgTy fun_ty
+ stop = case mb_arg_info of
Nothing -> mkBoringStop arg_ty
Just ai -> mkLazyArgStop arg_ty ai
; arg' <- simplExprC arg_env' arg stop
- ; return (Simplified, zapSubstEnv arg_env', arg') }
+ ; return (Simplified NoDup, arg') }
-- Return a StaticEnv that includes the in-scope set from 'env',
-- because arg' may well mention those variables (#20639)
@@ -1847,13 +1849,15 @@ simpl_lam env bndr body (ApplyToVal { sc_arg = Coercion arg_co, sc_env = arg_se
, sc_cont = cont })
= assertPpr (isCoVar bndr) (ppr bndr) $
do { tick (BetaReduction bndr)
- ; let arg_co' = substCo (arg_se `setInScopeFromE` env) arg_co
+ ; let arg_co' = case arg_se of
+ Simplified {} -> arg_co
+ UnSimplified arg_se -> substCo (arg_se `setInScopeFromE` env) arg_co
; simplLam (extendCvSubst env bndr arg_co') body cont }
-- Value beta-reduction
-- This works for /coercion/ lambdas too
simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
- , sc_cont = cont, sc_dup = dup
+ , sc_cont = cont
, sc_hole_ty = fun_ty})
= do { tick (BetaReduction bndr)
; let from_what = FromBeta arg_levity
@@ -1869,7 +1873,7 @@ simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
-- It's wrong to err in either direction
-- But fun_ty is an OutType, so is fully substituted
- ; if | Just env' <- preInlineUnconditionally env NotTopLevel bndr dup arg arg_se
+ ; if | Just env' <- preInlineUnconditionally env NotTopLevel bndr arg arg_se
, not (needsCaseBindingL arg_levity arg)
-- Ok to test arg::InExpr in needsCaseBinding because
-- exprOkForSpeculation is stable under simplification
@@ -1877,13 +1881,17 @@ simpl_lam env bndr body (ApplyToVal { sc_arg = arg, sc_env = arg_se
tick (PreInlineUnconditionally bndr)
; simplLam env' body cont }
- | isSimplified dup -- Don't re-simplify if we've simplified it once
- -- Including don't preInlineUnconditionally
- -- See Note [Avoiding simplifying repeatedly]
- -> completeBindX env from_what bndr arg body cont
-
| otherwise
- -> simplNonRecE env from_what bndr (arg, arg_se) body cont }
+ -> case arg_se of
+ Simplified {}
+ -- Don't re-simplify if we've simplified it once
+ -- Including don't preInlineUnconditionally
+ -- See Note [Avoiding simplifying repeatedly]
+ -> completeBindX env from_what bndr arg body cont
+
+ UnSimplified arg_env
+ -> simplNonRecE env from_what bndr (arg, arg_env) body cont
+ }
-- Discard a non-counting tick on a lambda. This may change the
-- cost attribution slightly (moving the allocation of the
@@ -1945,7 +1953,7 @@ simplNonRecE env from_what bndr (rhs, rhs_se) body cont
= -- Evaluate RHS strictly
simplExprF (rhs_se `setInScopeFromE` env) rhs
(StrictBind { sc_bndr = bndr, sc_body = body, sc_from = from_what
- , sc_env = env, sc_cont = cont, sc_dup = NoDup })
+ , sc_env = UnSimplified env, sc_cont = cont })
| otherwise -- Evaluate RHS lazily
= do { (env1, bndr1) <- simplNonRecBndr env bndr
@@ -2278,7 +2286,7 @@ simplInId :: SimplEnv -> InId -> SimplCont -> SimplM (SimplFloats, OutExpr)
simplInId env var cont
| Just dc <- isDataConWorkId_maybe var
, isLazyDataConRep dc -- See Note [Fast path for lazy data constructors]
- = rebuild_go zapped_env (Var var) cont
+ = rebuild env (Var var) cont
| otherwise
= case substId env var of
ContEx tvs cvs ids e -> simplExprF env' e cont
@@ -2299,13 +2307,18 @@ simplInId env var cont
---------------------------------------------------------
-simplOutExpr :: SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
+simplOutExpr :: HasDebugCallStack
+ => SimplEnvIS -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
-- A teeny-tiny simplifier for an OutExpr, which parsimonously avoids re-simplifying
-- the entire things all over again
--
-- What if expr = (K x y) and cont is `Select`? That is handled by rebuild.
-- (Why? That's a bit inconsistent with beta.)
simplOutExpr env expr cont
+ | assertPpr (checkSimplEnvIS env) (pprBadSimplEnvIS env) $
+ False -- Just checks the assertion!
+ = panic "simplOutExpr"
+
| Lam {} <- expr
, cont_has_args
= simplLam env (occurAnalyseExpr expr) cont
@@ -2326,7 +2339,7 @@ simplOutExpr env expr cont
-- pprTrace "simplOutExpr" (vcat [ ppr v <+> dcolon <+> ppr (idType v)
-- , text "args:" <+> ppr args
-- , text "cont:" <+> ppr cont ]) $
- simplOutId env v (pushArgs env (idType v) args cont)
+ simplOutId env v (pushArgs (idType v) args cont)
| otherwise
= rebuild_go env expr cont
@@ -2349,7 +2362,7 @@ simplOutId env fun cont
, sc_env = arg_se, sc_hole_ty = fun_ty } <- cont2
-- Do this even if (contIsStop cont), or if seCaseCase is off.
-- See Note [No eta-expansion in runRW#]
- = do { let arg_env = arg_se `setInScopeFromE` env
+ = do { let (_saf,arg_env) = mkAltEnv env arg_se
overall_res_ty = contResultType cont3
-- hole_ty is the type of the current runRW# application
@@ -2374,8 +2387,8 @@ simplOutId env fun cont
_ -> do { s' <- newId (fsLit "s") ManyTy realWorldStatePrimTy
; let (m,_,_) = splitFunTy fun_ty
env' = arg_env `addNewInScopeIds` [s']
- cont' = ApplyToVal { sc_dup = Simplified, sc_arg = Var s'
- , sc_env = env', sc_cont = inner_cont
+ cont' = ApplyToVal { sc_arg = Var s'
+ , sc_env = Simplified OkDup, sc_cont = inner_cont
, sc_hole_ty = mkVisFunTy m realWorldStatePrimTy new_runrw_res_ty }
-- cont' applies to s', then K
; body' <- simplExprC env' arg cont'
@@ -2460,30 +2473,23 @@ rebuildCall env info (ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_c
---------- Simplify value arguments --------------------
rebuildCall env fun_info
(ApplyToVal { sc_arg = arg, sc_env = arg_se
- , sc_dup = dup_flag, sc_hole_ty = fun_ty
- , sc_cont = cont })
- -- Argument is already simplified
- | isSimplified dup_flag -- See Note [Avoid redundant simplification]
- = rebuildCall env (addValArgTo fun_info arg fun_ty) cont
-
- -- Strict arguments
- | isStrictArgInfo fun_info
- , seCaseCase env -- Only when case-of-case is on. See GHC.Driver.Config.Core.Opt.Simplify
- -- Note [Case-of-case and full laziness]
- = -- pprTrace "Strict Arg" (ppr arg $$ ppr (seIdSubst env) $$ ppr (seInScope env)) $
- simplExprF (arg_se `setInScopeFromE` env) arg
+ , sc_hole_ty = fun_ty, sc_cont = cont })
+ | UnSimplified arg_env <- arg_se
+ , isStrictArgInfo fun_info -- Strict arguments
+ , seCaseCase env -- But only when case-of-case is on.
+ -- See Note [Case-of-case and full laziness]
+ = simplExprF (arg_env `setInScopeFromE` env) arg
(StrictArg { sc_fun = fun_info, sc_fun_ty = fun_ty
- , sc_dup = Simplified
+ , sc_dup = NoDup
, sc_cont = cont })
-- Note [Shadowing in the Simplifier]
- -- Lazy arguments
- | otherwise
- -- DO NOT float anything outside, hence simplExprC
- -- There is no benefit (unlike in a let-binding), and we'd
- -- have to be very careful about bogus strictness through
- -- floating a demanded let.
- = do { (_, _, arg') <- simplLazyArg env dup_flag fun_ty (Just fun_info) arg_se arg
+ | otherwise -- Lazy, or already simplified arguments
+ -- DO NOT float anything outside, hence simplExprC
+ -- There is no benefit (unlike in a let-binding), and we'd
+ -- have to be very careful about bogus strictness through
+ -- floating a demanded let.
+ = do { (_, arg') <- simplArg env fun_ty (Just fun_info) arg_se arg
; rebuildCall env (addValArgTo fun_info arg' fun_ty) cont }
---------- No further useful info, revert to generic rebuild ------------
@@ -2508,7 +2514,7 @@ tryInlining env logger var cont
= return Nothing
where
- (lone_variable, arg_infos, call_cont) = contArgs cont
+ (lone_variable, arg_infos, call_cont) = contArgs env cont
interesting_cont = interestingCallContext env call_cont
log_inlining doc
@@ -2685,8 +2691,8 @@ fireRuleAFTER env rule_match arg_specs cont
, rm_binds = wrap, rm_bndrs = bndrs } <- rule_match
= do { let env' = env `addNewInScopeIds` bndrs
; (floats, e') <- simplExprF env' rhs $
- pushArgs env' (exprType rhs) rhs_args $
- pushArgSpecs env' (drop (ruleArity rule) arg_specs) cont
+ pushArgs (exprType rhs) rhs_args $
+ pushArgSpecs (drop (ruleArity rule) arg_specs) cont
; return $
if isEmptyBindWrapper wrap -- Not very pretty
then (floats, e')
@@ -2797,9 +2803,8 @@ trySeqRules in_env scrut rhs cont
, ValArg { as_arg = no_cast_scrut
, as_dmd = seqDmd
, as_hole_ty = res3_ty } ]
- rule_cont = ApplyToVal { sc_dup = NoDup, sc_arg = rhs
- , sc_env = in_env, sc_cont = cont
- , sc_hole_ty = res4_ty }
+ rule_cont = ApplyToVal { sc_env = UnSimplified in_env, sc_arg = rhs
+ , sc_cont = cont, sc_hole_ty = res4_ty }
out_args = [Type rhs_rep, Type scrut_ty, Type rhs_ty, no_cast_scrut]
-- Cheaper than (map argSpecArg out_arg_specs)
@@ -3143,7 +3148,7 @@ We want to bind x' to x, and not to a duplicated (a,b)).
-- Eliminate the case if possible
rebuildCase, reallyRebuildCase
- :: SimplEnv
+ :: (SimplAltFlag, SimplEnv)
-> OutExpr -- Scrutinee
-> InId -- Case binder
-> [InAlt] -- Alternatives (increasing order)
@@ -3154,14 +3159,14 @@ rebuildCase, reallyRebuildCase
-- 1. Eliminate the case if there's a known constructor
--------------------------------------------------
-rebuildCase env scrut case_bndr alts cont
+rebuildCase (saf,env) scrut case_bndr alts cont
| Lit lit <- scrut -- No need for same treatment as constructors
-- because literals are inlined more vigorously
, not (litIsLifted lit)
= do { tick (KnownBranch case_bndr)
; case findAlt (LitAlt lit) alts of
Nothing -> missingAlt env case_bndr alts cont
- Just (Alt _ bs rhs) -> simple_rhs env scrut bs rhs }
+ Just (Alt _ bs rhs) -> simpl_rhs env scrut bs rhs }
| Just (in_scope', wfloats, con, ty_args, other_args)
<- exprIsConApp_maybe (getUnfoldingInRuleMatch env) scrut
@@ -3177,24 +3182,24 @@ rebuildCase env scrut case_bndr alts cont
; wrapDataConFloats env wfloats case_bndr cont $
case findAlt (DataAlt con) alts of
Nothing -> missingAlt env0 case_bndr alts cont
- Just (Alt DEFAULT bs rhs) -> simple_rhs env0 case_bndr_rhs bs rhs
- Just (Alt _ bs rhs) -> knownCon env0 scrut con
- other_args case_bndr bs rhs cont
+ Just (Alt DEFAULT bs rhs) -> simpl_rhs env0 case_bndr_rhs bs rhs
+ Just (Alt _ bs rhs) -> knownCon env0 scrut con other_args
+ case_bndr bs rhs cont
}
where
- simple_rhs env case_bndr_rhs bs rhs =
- assert (null bs) $
- do { (floats1, env') <- simplAuxBind "rebuildCase" env case_bndr case_bndr_rhs
- -- scrut is a constructor application,
- -- hence satisfies let-can-float invariant
- ; (floats2, expr') <- simplExprF env' rhs cont
- ; return (floats1 `addFloats` floats2, expr') }
+ simpl_rhs env case_bndr_rhs bs rhs
+ = assert (null bs) $
+ do { (floats1, env') <- simplAuxBind (saf,env) case_bndr case_bndr_rhs
+ -- scrut is a constructor application,
+ -- hence satisfies let-can-float invariant
+ ; (floats2, expr') <- simplExprF env' rhs cont
+ ; return (floats1 `addFloats` floats2, expr') }
--------------------------------------------------
-- 2. Eliminate the case if scrutinee is evaluated
--------------------------------------------------
-rebuildCase env scrut case_bndr alts@[Alt _ bndrs rhs] cont
+rebuildCase (saf,env) scrut case_bndr alts@[Alt _ bndrs rhs] cont
-- See if we can get rid of the case altogether
-- See Note [Case elimination]
-- mkCase made sure that if all the alternatives are equal,
@@ -3218,7 +3223,9 @@ rebuildCase env scrut case_bndr alts@[Alt _ bndrs rhs] cont
| all_dead_bndrs
, doCaseToLet scrut case_bndr
= do { tick (CaseElim case_bndr)
- ; (floats1, env') <- simplAuxBind "rebuildCaseAlt1" env case_bndr scrut
+ ; (floats1, env') <- simplAuxBind (saf,env) case_bndr scrut
+ -- simplAuxBind can create a substitution for case_bndr,
+ -- so we must re-simpify `rhs` regardless of `saf`
; (floats2, expr') <- simplExprF env' rhs cont
; return (floats1 `addFloats` floats2, expr') }
@@ -3230,22 +3237,22 @@ rebuildCase env scrut case_bndr alts@[Alt _ bndrs rhs] cont
= do { mb_rule <- trySeqRules env scrut rhs cont
; case mb_rule of
Just (rm, ass, rcont) -> fireRuleAFTER env rm ass rcont
- Nothing -> reallyRebuildCase env scrut case_bndr alts cont }
+ Nothing -> reallyRebuildCase (saf,env) scrut case_bndr alts cont }
where
all_dead_bndrs = all isDeadBinder bndrs -- bndrs are [InId]
is_plain_seq = all_dead_bndrs && isDeadBinder case_bndr -- Evaluation *only* for effect
-rebuildCase env scrut case_bndr alts cont
+rebuildCase (saf,env) scrut case_bndr alts cont
--------------------------------------------------
-- 3. Primop-related case-rules
--------------------------------------------------
| Just (scrut', case_bndr', alts') <- caseRules2 (sePlatform env) scrut case_bndr alts
- = reallyRebuildCase env scrut' case_bndr' alts' cont
+ = reallyRebuildCase (saf,env) scrut' case_bndr' alts' cont
| otherwise
- = reallyRebuildCase env scrut case_bndr alts cont
+ = reallyRebuildCase (saf,env) scrut case_bndr alts cont
doCaseToLet :: OutExpr -- Scrutinee
-> InId -- Case binder
@@ -3276,17 +3283,17 @@ doCaseToLet scrut case_bndr
-- 3. Catch-all case
--------------------------------------------------
-reallyRebuildCase env scrut case_bndr alts cont
+reallyRebuildCase (saf,env) scrut case_bndr alts cont
| not (seCaseCase env) -- Only when case-of-case is on.
-- See GHC.Driver.Config.Core.Opt.Simplify
-- Note [Case-of-case and full laziness]
- = do { case_expr <- simplAlts env scrut case_bndr alts
+ = do { case_expr <- simplAlts (saf,env) scrut case_bndr alts
(mkBoringStop (contHoleType cont))
; rebuild env case_expr cont }
| otherwise
= do { (floats, env', cont') <- mkDupableCaseCont env alts cont
- ; case_expr <- simplAlts env' scrut
+ ; case_expr <- simplAlts (saf,env') scrut
(scaleIdBy holeScaling case_bndr)
(scaleAltsBy holeScaling alts)
cont'
@@ -3427,24 +3434,23 @@ scale the entire case we are simplifying, by a scaling factor which can be
computed in the continuation (with function `contHoleScaling`).
-}
-simplAlts :: SimplEnv
- -> OutExpr -- Scrutinee
- -> InId -- Case binder
- -> [InAlt] -- Non-empty
+simplAlts :: (SimplAltFlag, SimplEnv)
+ -> OutExpr -- Scrutinee
+ -> InId -> [InAlt] -- Alts (non-empty)
-> SimplCont
-> SimplM OutExpr -- Returns the complete simplified case expression
-simplAlts env0 scrut case_bndr alts cont'
+simplAlts (saf,env0) scrut case_bndr alts cont'
= do { traceSmpl "simplAlts" (vcat [ ppr case_bndr
, text "cont':" <+> ppr cont'
, text "in_scope" <+> ppr (seInScope env0) ])
- ; (env1, case_bndr1) <- simplBinder env0 case_bndr
+ ; (env1, case_bndr1) <- simplAltIdBinder (saf,env0) case_bndr
; let case_bndr2 = case_bndr1 `setIdUnfolding` evaldUnfolding
env2 = modifyInScope env1 case_bndr2
-- See Note [Case binder evaluated-ness]
fam_envs = seFamEnvs env0
- ; (alt_env', scrut', case_bndr') <- improveSeq fam_envs env2 scrut
+ ; (alt_env', scrut', case_bndr') <- improveSeq fam_envs (saf,env2) scrut
case_bndr case_bndr2 alts
; (imposs_deflt_cons, in_alts) <- prepareAlts scrut' case_bndr alts
@@ -3454,7 +3460,7 @@ simplAlts env0 scrut case_bndr alts cont'
-- See Note [Shadowing in prepareAlts] in GHC.Core.Opt.Simplify.Utils
; alts' <- forM in_alts $
- simplAlt alt_env' (Just scrut') imposs_deflt_cons
+ simplAlt (saf,alt_env') (Just scrut') imposs_deflt_cons
case_bndr' (scrutOkForBinderSwap scrut) cont'
; let alts_ty' = contResultType cont'
@@ -3464,23 +3470,25 @@ simplAlts env0 scrut case_bndr alts cont'
------------------------------------
-improveSeq :: (FamInstEnv, FamInstEnv) -> SimplEnv
+improveSeq :: (FamInstEnv, FamInstEnv)
+ -> (SimplAltFlag, SimplEnv)
-> OutExpr -> InId -> OutId -> [InAlt]
-> SimplM (SimplEnv, OutExpr, OutId)
-- Note [Improving seq]
-improveSeq fam_envs env scrut case_bndr case_bndr1 [Alt DEFAULT _ _]
- | Just (Reduction co ty2) <- topNormaliseType_maybe fam_envs (idType case_bndr1)
+improveSeq fam_envs (saf,env) scrut case_bndr case_bndr1 [Alt DEFAULT _ _]
+ | SAF_In <- saf -- improveSeq extends the substitution; not allowed for SAF_Out
+ , Just (Reduction co ty2) <- topNormaliseType_maybe fam_envs (idType case_bndr1)
= do { case_bndr2 <- newId (fsLit "nt") ManyTy ty2
; let rhs = DoneEx (Var case_bndr2 `Cast` mkSymCo co) NotJoinPoint
env2 = extendIdSubst env case_bndr rhs
; return (env2, scrut `Cast` co, case_bndr2) }
-improveSeq _ env scrut _ case_bndr1 _
+improveSeq _ (_,env) scrut _ case_bndr1 _
= return (env, scrut, case_bndr1)
------------------------------------
-simplAlt :: SimplEnv
+simplAlt :: (SimplAltFlag, SimplEnv)
-> Maybe OutExpr -- The scrutinee
-> [AltCon] -- These constructors can't be present when
-- matching the DEFAULT alternative
@@ -3491,26 +3499,27 @@ simplAlt :: SimplEnv
-> InAlt
-> SimplM OutAlt
-simplAlt env _scrut' imposs_deflt_cons case_bndr' bndr_swap' cont' (Alt DEFAULT bndrs rhs)
+simplAlt (saf,env) _scrut' imposs_deflt_cons case_bndr' bndr_swap' cont' (Alt DEFAULT bndrs rhs)
= assert (null bndrs) $
do { let env' = addDefaultUnfoldings env case_bndr' bndr_swap' imposs_deflt_cons
- ; rhs' <- simplExprC env' rhs cont'
+ ; rhs' <- simplAltExprC (saf,env') rhs cont'
; return (Alt DEFAULT [] rhs') }
-simplAlt env _scrut' _ case_bndr' bndr_swap' cont' (Alt (LitAlt lit) bndrs rhs)
+simplAlt (saf,env) _scrut' _ case_bndr' bndr_swap' cont' (Alt (LitAlt lit) bndrs rhs)
= assert (null bndrs) $
do { let env' = addAltUnfoldings env case_bndr' bndr_swap' (Lit lit)
- ; rhs' <- simplExprC env' rhs cont'
+ ; rhs' <- simplAltExprC (saf,env') rhs cont'
; return (Alt (LitAlt lit) [] rhs') }
-simplAlt env scrut' _ case_bndr' bndr_swap' cont' (Alt (DataAlt con) vs rhs)
+simplAlt (saf,env) scrut' _ case_bndr' bndr_swap' cont' (Alt (DataAlt con) vs rhs)
= do { -- See Note [Adding evaluatedness info to pattern-bound variables]
-- and Note [DataAlt occ info]
; let vs_with_info = adjustFieldsIdInfo scrut' case_bndr' bndr_swap' con vs
-- Adjust evaluated-ness and occ-info flags before `simplBinders`
-- because the latter extends the in-scope set, which propagates this
-- adjusted info to use sites.
- ; (env', vs') <- simplBinders env vs_with_info
+
+ ; (env', vs') <- simplAltBinders (saf,env) vs_with_info
-- Bind the case-binder to (con args)
; let inst_tys' = tyConAppArgs (idType case_bndr')
@@ -3518,7 +3527,7 @@ simplAlt env scrut' _ case_bndr' bndr_swap' cont' (Alt (DataAlt con) vs rhs)
con_app = mkConApp2 con inst_tys' vs'
env'' = addAltUnfoldings env' case_bndr' bndr_swap' con_app
- ; rhs' <- simplExprC env'' rhs cont'
+ ; rhs' <- simplAltExprC (saf,env'') rhs cont'
; return (Alt (DataAlt con) vs' rhs') }
{- Note [Adding evaluatedness info to pattern-bound variables]
@@ -3665,6 +3674,40 @@ zapBndrOccInfo keep_occ_info pat_id
| keep_occ_info = pat_id
| otherwise = zapIdOccInfo pat_id
+
+data SimplAltFlag = SAF_In -- Must run the simplifier, or at least substitution
+ | SAF_Out -- No need to run the simplifier; substitution is empty
+
+mkAltEnv :: SimplEnvIS -> StaticEnv -> (SimplAltFlag, SimplEnv)
+mkAltEnv env (Simplified {}) = (SAF_Out, env)
+mkAltEnv env (UnSimplified se) = (SAF_In, se`setInScopeFromE` env)
+
+simplAltBinders :: (SimplAltFlag, SimplEnv) -> [Var] -> SimplM (SimplEnv, [OutVar])
+simplAltBinders (saf,env) bs
+ = case saf of
+ SAF_Out -> return (env, bs)
+ SAF_In -> simplBinders env bs
+
+simplAltIdBinder :: (SimplAltFlag, SimplEnv) -> Id -> SimplM (SimplEnv, OutId)
+simplAltIdBinder (saf,env) bndr
+ = case saf of
+ SAF_Out -> return (env, bndr)
+ SAF_In -> simplNonRecBndr env bndr
+
+simplAltExprF :: HasDebugCallStack
+ => (SimplAltFlag, SimplEnv) -> CoreExpr -> SimplCont
+ -> SimplM (SimplFloats, OutExpr)
+simplAltExprF (saf,env) expr cont
+ = case saf of
+ SAF_Out -> simplOutExpr env expr cont
+ SAF_In -> simplExprF env expr cont
+
+simplAltExprC :: (SimplAltFlag, SimplEnv) -> CoreExpr -> SimplCont -> SimplM OutExpr
+simplAltExprC env expr cont
+ = do { (floats, expr') <- simplAltExprF env expr cont
+ ; return (wrapFloats floats expr') }
+
+
{- Note [Case binder evaluated-ness]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We pin on a (OtherCon []) unfolding to the case-binder of a Case,
@@ -3799,12 +3842,13 @@ wrapDataConFloats env wfloats case_bndr cont thing_inside
knownCon :: SimplEnv
- -> OutExpr -- The scrutinee
- -> DataCon -> [OutExpr] -- The scrutinee (in pieces)
- -> InId -> [InBndr] -> InExpr -- The alternative
+ -> OutExpr -- The scrutinee
+ -> DataCon -> [OutExpr] -- The scrutinee (in pieces)
+ -> InId -> [InBndr] -> InExpr -- The alternative
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
-
+-- We do not pass SimplAltFlag to knownCon because we really do want
+-- to simplify the RHS, with the new knowledge about the case-simplification
knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont
= do { (floats1, env1) <- bind_args env alt_bndrs dc_args
; (floats2, env2) <- bind_case_bndr env1
@@ -3831,7 +3875,8 @@ knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont
-- occur in the RHS; and simplAuxBind may therefore discard it.
-- Nevertheless we must keep it if the case-binder is alive,
-- because it may be used in the con_app. See Note [knownCon occ info]
- ; (floats1, env2) <- simplAuxBind "knownCon" env' b' arg -- arg satisfies let-can-float invariant
+ ; (floats1, env2) <- simplAuxBind (SAF_In,env') b' arg
+ -- arg satisfies let-can-float invariant
; (floats2, env3) <- bind_args env2 bs' args
; return (floats1 `addFloats` floats2, env3) }
@@ -3855,11 +3900,11 @@ knownCon env scrut dc dc_args case_bndr alt_bndrs rhs cont
return ( emptyFloats env
, extendIdSubst env case_bndr (DoneEx scrut NotJoinPoint))
- | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr NoDup con_app env
+ | Just env' <- preInlineUnconditionally env NotTopLevel case_bndr con_app (UnSimplified env)
= return (emptyFloats env', env')
| otherwise
- = do { (env1, case_bndr1) <- simplNonRecBndr env case_bndr
+ = do { (env1, case_bndr1) <- simplAltIdBinder (SAF_In,env) case_bndr
; simplLazyBind NotTopLevel NonRecursive
(case_bndr,env) (case_bndr1,env1) (con_app,env) }
@@ -3918,9 +3963,9 @@ join points and inlining them away. See #4930.
-}
--------------------
-mkDupableCaseCont :: SimplEnv -> [InAlt] -> SimplCont
+mkDupableCaseCont :: SimplEnvIS -> [InAlt] -> SimplCont
-> SimplM ( SimplFloats -- Join points (if any)
- , SimplEnv -- Use this for the alts
+ , SimplEnvIS -- Use this for the alts
, SimplCont)
mkDupableCaseCont env alts cont
| altsWouldDup alts = do { (floats, cont) <- mkDupableCont env cont
@@ -3940,7 +3985,7 @@ altsWouldDup (alt:alts)
is_bot_alt (Alt _ _ rhs) = exprIsDeadEnd rhs
-------------------------
-mkDupableCont :: SimplEnv
+mkDupableCont :: SimplEnvIS
-> SimplCont
-> SimplM ( SimplFloats -- Incoming SimplEnv augmented with
-- extra let/join-floats and in-scope variables
@@ -3974,12 +4019,17 @@ mkDupableContWithDmds env dmds (TickIt t cont)
; return (floats, TickIt t cont') }
mkDupableContWithDmds env _
- (StrictBind { sc_bndr = bndr, sc_body = body, sc_from = from_what
- , sc_env = se, sc_cont = cont})
+ cont1@(StrictBind { sc_bndr = bndr, sc_body = body, sc_from = from_what
+ , sc_env = se, sc_cont = cont})
-- See Note [Duplicating StrictBind]
-- K[ let x = <> in b ] --> join j x = K[ b ]
-- j <>
- = do { let sb_env = se `setInScopeFromE` env
+ = do { let sb_env = case se of
+ UnSimplified static_env -> static_env `setInScopeFromE` env
+ Simplified {} -> pprPanic "mkDupableContWithDmds" (ppr se $$ ppr cont1)
+ -- The contIsDupable caught the OkDup case, and
+ -- we never build a StrictBind with a NoDup in it.
+
; (sb_env1, bndr') <- simplBinder sb_env bndr
; (floats1, join_inner) <- simplNonRecBody sb_env1 from_what body cont
-- No need to use mkDupableCont before simplNonRecBody; we
@@ -4009,7 +4059,7 @@ mkDupableContWithDmds env _
, StrictArg { sc_fun = fun { ai_args = args' }
, sc_cont = cont'
, sc_fun_ty = fun_ty
- , sc_dup = OkToDup} ) }
+ , sc_dup = OkDup} ) }
| otherwise
= -- Use Plan B of Note [Duplicating StrictArg]
@@ -4038,7 +4088,7 @@ mkDupableContWithDmds env dmds
, sc_arg_ty = arg_ty, sc_hole_ty = hole_ty }) }
mkDupableContWithDmds env dmds
- (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_env = se
+ (ApplyToVal { sc_arg = arg, sc_env = se
, sc_cont = cont, sc_hole_ty = hole_ty })
= -- e.g. [...hole...] (...arg...)
-- ==>
@@ -4048,18 +4098,12 @@ mkDupableContWithDmds env dmds
do { let dmd:|cont_dmds = expectNonEmpty dmds
; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
; let env' = env `setInScopeFromF` floats1
- ; (_, se', arg') <- simplLazyArg env' dup hole_ty Nothing se arg
- ; (let_floats2, arg'') <- makeTrivial env NotTopLevel dmd (fsLit "karg") arg'
+ ; (_, arg') <- simplArg env' hole_ty Nothing se arg
+ ; (let_floats2, triv_arg) <- makeTrivial env' NotTopLevel dmd (fsLit "karg") arg'
; let all_floats = floats1 `addLetFloats` let_floats2
; return ( all_floats
- , ApplyToVal { sc_arg = arg''
- , sc_env = se' `setInScopeFromF` all_floats
- -- Ensure that sc_env includes the free vars of
- -- arg'' in its in-scope set, even if makeTrivial
- -- has turned arg'' into a fresh variable
- -- See Note [StaticEnv invariant] in GHC.Core.Opt.Simplify.Utils
- , sc_dup = OkToDup, sc_cont = cont'
- , sc_hole_ty = hole_ty }) }
+ , ApplyToVal { sc_arg = triv_arg, sc_env = Simplified OkDup
+ , sc_cont = cont', sc_hole_ty = hole_ty }) }
mkDupableContWithDmds env _
(Select { sc_bndr = case_bndr, sc_alts = alts, sc_env = se, sc_cont = cont })
@@ -4069,16 +4113,20 @@ mkDupableContWithDmds env _
-- in case [...hole...] of { pi -> ji xij }
-- NB: sc_dup /= OkToDup; that is caught earlier by contIsDupable
do { tick (CaseOfCase case_bndr)
- ; (floats, alt_env, alt_cont) <- mkDupableCaseCont (se `setInScopeFromE` env) alts cont
+ ; (floats, env1, alt_cont) <- mkDupableCaseCont env alts cont
-- NB: We call mkDupableCaseCont here to make cont duplicable
-- (if necessary, depending on the number of alts)
-- And this is important: see Note [Fusing case continuations]
; let cont_scaling = contHoleScaling cont
+ (saf, alt_env) = mkAltEnv env1 se
+
-- See Note [Scaling in case-of-case]
- ; (alt_env', case_bndr') <- simplBinder alt_env (scaleIdBy cont_scaling case_bndr)
+ ; (alt_env1, case_bndr') <- simplAltIdBinder (saf,alt_env) $
+ scaleIdBy cont_scaling case_bndr
+
; alts' <- forM (scaleAltsBy cont_scaling alts) $
- simplAlt alt_env' Nothing [] case_bndr' NoBinderSwap alt_cont
+ simplAlt (saf,alt_env1) Nothing [] case_bndr' NoBinderSwap alt_cont
-- Safe to say that there are no handled-cons for the DEFAULT case
-- NB: simplBinder does not zap deadness occ-info, so
-- a dead case_bndr' will still advertise its deadness
@@ -4097,11 +4145,8 @@ mkDupableContWithDmds env _
; let all_floats = floats `addJoinFloats` join_floats
-- Note [Duplicated env]
; return (all_floats
- , Select { sc_dup = OkToDup
- , sc_bndr = case_bndr'
- , sc_alts = alts''
- , sc_env = zapSubstEnv se `setInScopeFromF` all_floats
- -- See Note [StaticEnv invariant] in GHC.Core.Opt.Simplify.Utils
+ , Select { sc_bndr = case_bndr', sc_alts = alts''
+ , sc_env = Simplified OkDup
, sc_cont = mkBoringStop (contResultType cont) } ) }
mkDupableStrictBind :: SimplEnv -> OutId -> OutExpr -> OutType
@@ -4112,10 +4157,9 @@ mkDupableStrictBind env arg_bndr join_rhs res_ty
= return (emptyFloats env
, StrictBind { sc_bndr = arg_bndr
, sc_body = join_rhs
- , sc_env = zapSubstEnv env
+ , sc_env = Simplified OkDup
+ -- See Note [StaticEnv] in GHC.Core.Opt.Simplify.Utils
, sc_from = FromLet
- -- See Note [StaticEnv invariant] in GHC.Core.Opt.Simplify.Utils
- , sc_dup = OkToDup
, sc_cont = mkBoringStop res_ty } )
| otherwise
= do { join_bndr <- newJoinId [arg_bndr] res_ty
@@ -4127,7 +4171,7 @@ mkDupableStrictBind env arg_bndr join_rhs res_ty
unitJoinFloat $
NonRec join_bndr $
Lam (setOneShotLambda arg_bndr) join_rhs
- , StrictArg { sc_dup = OkToDup
+ , StrictArg { sc_dup = OkDup
, sc_fun = arg_info
, sc_fun_ty = idType join_bndr
, sc_cont = mkBoringStop res_ty
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -21,7 +21,8 @@ module GHC.Core.Opt.Simplify.Utils (
BindContext(..), bindContextLevel,
-- The continuation type
- SimplCont(..), DupFlag(..), FromWhat(..), StaticEnv,
+ SimplCont(..), DupFlag(..), FromWhat(..),
+ StaticEnv(..),
isSimplified, contIsStop,
contIsDupable, contResultType, contHoleType, contHoleScaling,
contIsTrivial, contArgs, contIsRhs,
@@ -171,11 +172,10 @@ data SimplCont
, sc_cont :: SimplCont }
| ApplyToVal -- (ApplyToVal arg K)[e] = K[ e arg ]
- { sc_dup :: DupFlag -- See Note [DupFlag invariants]
- , sc_hole_ty :: OutType -- Type of the function, presumably (forall a. blah)
+ { sc_hole_ty :: OutType -- Type of the function, presumably (forall a. blah)
-- See Note [The hole type in ApplyToTy]
- , sc_arg :: InExpr -- The argument,
- , sc_env :: StaticEnv -- see Note [StaticEnv invariant]
+ , sc_env :: StaticEnv -- See Note [StaticEnv]
+ , sc_arg :: CoreExpr -- The argument,
, sc_cont :: SimplCont }
| ApplyToTy -- (ApplyToTy ty K)[e] = K[ e ty ]
@@ -185,25 +185,24 @@ data SimplCont
, sc_cont :: SimplCont }
| Select -- (Select alts K)[e] = K[ case e of alts ]
- { sc_dup :: DupFlag -- See Note [DupFlag invariants]
- , sc_bndr :: InId -- case binder
- , sc_alts :: [InAlt] -- Alternatives
- , sc_env :: StaticEnv -- See Note [StaticEnv invariant]
+ { sc_env :: StaticEnv -- See Note [StaticEnv]
+ , sc_bndr :: Id -- Case binder
+ , sc_alts :: [CoreAlt] -- Alternatives
, sc_cont :: SimplCont }
-- The two strict forms have no DupFlag, because we never duplicate them
| StrictBind -- (StrictBind x b K)[e] = let x = e in K[b]
-- or, equivalently, = K[ (\x.b) e ]
- { sc_dup :: DupFlag -- See Note [DupFlag invariants]
- , sc_from :: FromWhat
- , sc_bndr :: InId
- , sc_body :: InExpr
- , sc_env :: StaticEnv -- Static env for both sc_bndr (stable unfolding thereof)
- -- and sc_body. Also see Note [StaticEnv invariant]
+ { sc_from :: FromWhat
+ , sc_env :: StaticEnv -- See Note [StaticEnv]
+ -- The sc_env in StrictBind is never (Simplified NoDup)
+ , sc_bndr :: Id
+ , sc_body :: CoreExpr
+
, sc_cont :: SimplCont }
| StrictArg -- (StrictArg (f e1 ..en) K)[e] = K[ f e1 .. en e ]
- { sc_dup :: DupFlag -- Always Simplified or OkToDup
+ { sc_dup :: DupFlag
, sc_fun :: ArgInfo -- Specifies f, e1..en, Whether f has rules, etc
-- plus demands and discount flags for *this* arg
-- and further args
@@ -217,60 +216,82 @@ data SimplCont
CoreTickish -- Tick tickish <hole>
SimplCont
-type StaticEnv = SimplEnv -- Just the static part is relevant
+data StaticEnv -- See Note [StaticEnv]
+ = Simplified DupFlag -- No static env needed
+ | UnSimplified SimplEnv -- Just the static part is relevant
data FromWhat = FromLet | FromBeta Levity
--- See Note [DupFlag invariants]
-data DupFlag = NoDup -- Unsimplified, might be big
- | Simplified -- Simplified
- | OkToDup -- Simplified and small
-
-isSimplified :: DupFlag -> Bool
-isSimplified NoDup = False
-isSimplified _ = True -- Invariant: the subst-env is empty
-
-perhapsSubstTy :: DupFlag -> StaticEnv -> Type -> Type
-perhapsSubstTy dup env ty
- | isSimplified dup = ty
- | otherwise = substTy env ty
-
-{- Note [StaticEnv invariant]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We pair up an InExpr or InAlts with a StaticEnv, which establishes the
-lexical scope for that InExpr.
-
-When we simplify that InExpr/InAlts, we use
- - Its captured StaticEnv
- - Overriding its InScopeSet with the larger one at the
- simplification point.
-
-Why override the InScopeSet? Example:
- (let y = ey in f) ex
-By the time we simplify ex, 'y' will be in scope.
-
-However the InScopeSet in the StaticEnv is not irrelevant: it should
-include all the free vars of applying the substitution to the InExpr.
-Reason: contHoleType uses perhapsSubstTy to apply the substitution to
-the expression, and that (rightly) gives ASSERT failures if the InScopeSet
-isn't big enough.
-
-Note [DupFlag invariants]
-~~~~~~~~~~~~~~~~~~~~~~~~~
-In both ApplyToVal { se_dup = dup, se_env = env, se_cont = k}
- and Select { se_dup = dup, se_env = env, se_cont = k}
-the following invariants hold
-
- (a) if dup = OkToDup, then continuation k is also ok-to-dup
- (b) if dup = OkToDup or Simplified, the subst-env is empty,
- or at least is always ignored; the payload is
- already an OutThing
+data DupFlag = NoDup -- Too big (or unknown) to dup
+ | OkDup -- Small enough to dup
+
+okToDup :: DupFlag -> Bool
+okToDup NoDup = False
+okToDup OkDup = True
+
+okToDupSE :: StaticEnv -> Bool
+okToDupSE (Simplified dup) = okToDup dup
+okToDupSE (UnSimplified {}) = False
+
+isSimplified :: StaticEnv -> Bool
+isSimplified (Simplified {}) = True
+isSimplified (UnSimplified {}) = False
+
+perhapsSubstTy :: StaticEnv -> Type -> Type
+perhapsSubstTy (Simplified {}) ty = ty
+perhapsSubstTy (UnSimplified env) ty = substTy env ty
+
+
+{- Note [StaticEnv]
+~~~~~~~~~~~~~~~~~~~
+Consider ApplyToVal, which has
+ sc_env :: StaticEnv
+ sc_arg :: CoreExpr
+Initially, `sc_arg` is an un-simplified InExpr, and `sc_env` is (UnSimplified env),
+where `env` gives meaning to the free variables of `sc_arg`; in particular, `env`
+may have substitutions that must apply to the argument.
+
+But sometimes we simplify the argument, and in that case, `sc_arg` is an OutExpr,
+the simplified argument, and `sc_env` is (Simplified NoDup) or (Simplified OkDup).
+The former is the safe, conservative option, but in `mkDupableCont` we want to make
+the continuation duplicable, so we make the argument small and tag it with
+(Simplified OkDup).
+
+We later simplify the argument, e.g. in `simplArg`. Then
+ * If sc_env is Simplified, it's a no-op
+ * If sc_env is (UnSimplified arg_env) we simplify `sc_arg` with
+ - Its captured envt `arg_env`
+ - but overriding its InScopeSet with the larger one at the
+ simplification point.
+ Why override the InScopeSet? Example:
+ (let y = ey in f) ex
+ By the time we simplify ex, 'y' will be in scope.
+ All this is done in `simplArg`.
+
+Note that:
+
+* In the Simplified case there is no environment, because the substitution has
+ already been applied.
+
+* We say sc_arg :: CoreExpr, rather than sc_arg :: InExpr or sc_arg :: OutExpr,
+ because whether it is InExpr or OutExpr depends on `sc_env`
+
+* Same deal for Select, and StrictBind, but the StaticEnv scopes over
+ * sc_bndr and sc_alts (for Select)
+ * sc_bndr and sc_body (for StrictBind)
+
+* Even though the InScopeSet of an (UnSimplified se) is overridden in `simplArg`,
+ that InScopeSet is not irrelevant: it should include all the free vars of
+ applying the substitution to the InExpr. Reason: contHoleType uses perhapsSubstTy
+ to apply the substitution to the expression, and that (rightly) gives ASSERT
+ failures if the InScopeSet isn't big enough.
+
+(SE1) If dup = OkToDup, then continuation k is also ok-to-dup
-}
instance Outputable DupFlag where
- ppr OkToDup = text "ok"
- ppr NoDup = text "nodup"
- ppr Simplified = text "simpl"
+ ppr OkDup = text "okdup"
+ ppr NoDup = text "nodup"
instance Outputable SimplCont where
ppr (Stop ty interesting eval_sd)
@@ -283,18 +304,21 @@ instance Outputable SimplCont where
= (text "TickIt" <+> ppr t) $$ ppr cont
ppr (ApplyToTy { sc_arg_ty = ty, sc_cont = cont })
= (text "ApplyToTy" <+> pprParendType ty) $$ ppr cont
- ppr (ApplyToVal { sc_arg = arg, sc_dup = dup, sc_cont = cont, sc_hole_ty = hole_ty })
- = (hang (text "ApplyToVal" <+> ppr dup <+> text "hole-ty:" <+> pprParendType hole_ty)
+ ppr (ApplyToVal { sc_arg = arg, sc_env = env, sc_cont = cont, sc_hole_ty = hole_ty })
+ = (hang (text "ApplyToVal" <> braces (ppr env) <+> text "hole-ty:" <+> pprParendType hole_ty)
2 (pprParendExpr arg))
$$ ppr cont
ppr (StrictBind { sc_bndr = b, sc_cont = cont })
= (text "StrictBind" <+> ppr b) $$ ppr cont
ppr (StrictArg { sc_fun = ai, sc_cont = cont })
= (text "StrictArg" <+> ppr (ai_fun ai)) $$ ppr cont
- ppr (Select { sc_dup = dup, sc_bndr = bndr, sc_alts = alts, sc_cont = cont })
- = (text "Select" <+> ppr dup <+> ppr bndr) $$
+ ppr (Select { sc_env = env, sc_bndr = bndr, sc_alts = alts, sc_cont = cont })
+ = (text "Select" <> braces (ppr env) <+> ppr bndr) $$
whenPprDebug (nest 2 $ ppr alts) $$ ppr cont
+instance Outputable StaticEnv where
+ ppr (Simplified dup) = ppr dup
+ ppr (UnSimplified _env) = text "in" -- For InExpr etc
{- Note [The hole type in ApplyToTy]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -384,30 +408,27 @@ isStrictArgInfo (ArgInfo { ai_dmds = dmds })
| dmd:_ <- dmds = isStrUsedDmd dmd
| otherwise = False
-pushArgs :: SimplEnvIS -> Type -> [OutExpr] -> SimplCont -> SimplCont
-pushArgs _env _fun_ty [] cont
+pushArgs :: Type -> [OutExpr] -> SimplCont -> SimplCont
+pushArgs _fun_ty [] cont
= cont
-pushArgs env fun_ty (arg:args) cont
+pushArgs fun_ty (arg:args) cont
| Type ty <- arg
= ApplyToTy { sc_hole_ty = fun_ty, sc_arg_ty = ty
- , sc_cont = pushArgs env (piResultTy fun_ty ty) args cont }
+ , sc_cont = pushArgs (piResultTy fun_ty ty) args cont }
| otherwise
- = ApplyToVal { sc_dup = Simplified, sc_hole_ty = fun_ty
- , sc_arg = arg, sc_env = env
- , sc_cont = pushArgs env (funResultTy fun_ty) args cont}
+ = ApplyToVal { sc_hole_ty = fun_ty
+ , sc_arg = arg, sc_env = Simplified NoDup
+ , sc_cont = pushArgs (funResultTy fun_ty) args cont}
-pushArgSpecs :: SimplEnvIS -- Barely needed, since sc_dup = Simplified
- -> [ArgSpec] -- In normal, forward order
+pushArgSpecs :: [ArgSpec] -- In normal, forward order
-> SimplCont -> SimplCont
-pushArgSpecs env args cont = foldr (pushArgSpec env) cont args
--- pushSimplifiedRevArgs env args cont = foldl' (\k a -> pushSimplifiedArg env a k) cont args
+pushArgSpecs args cont = foldr pushArgSpec cont args
-pushArgSpec :: SimplEnvIS -> ArgSpec -> SimplCont -> SimplCont
-pushArgSpec _env (TyArg { as_arg_ty = arg_ty, as_hole_ty = hole_ty }) cont
+pushArgSpec :: ArgSpec -> SimplCont -> SimplCont
+pushArgSpec (TyArg { as_arg_ty = arg_ty, as_hole_ty = hole_ty }) cont
= ApplyToTy { sc_arg_ty = arg_ty, sc_hole_ty = hole_ty, sc_cont = cont }
-pushArgSpec env (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
- = ApplyToVal { sc_arg = arg, sc_env = env, sc_dup = Simplified
- -- The SubstEnv will be ignored since sc_dup=Simplified
+pushArgSpec (ValArg { as_arg = arg, as_hole_ty = hole_ty }) cont
+ = ApplyToVal { sc_arg = arg, sc_env = Simplified NoDup
, sc_hole_ty = hole_ty, sc_cont = cont }
argSpecArg :: ArgSpec -> OutExpr
@@ -456,13 +477,14 @@ contIsStop (Stop {}) = True
contIsStop _ = False
contIsDupable :: SimplCont -> Bool
-contIsDupable (Stop {}) = True
-contIsDupable (ApplyToTy { sc_cont = k }) = contIsDupable k
-contIsDupable (ApplyToVal { sc_dup = OkToDup }) = True -- See Note [DupFlag invariants]
-contIsDupable (Select { sc_dup = OkToDup }) = True -- ...ditto...
-contIsDupable (StrictArg { sc_dup = OkToDup }) = True -- ...ditto...
-contIsDupable (CastIt { sc_cont = k }) = contIsDupable k
-contIsDupable _ = False
+contIsDupable (Stop {}) = True
+contIsDupable (ApplyToTy { sc_cont = k }) = contIsDupable k
+contIsDupable (ApplyToVal { sc_env = se }) = okToDupSE se -- See (SE1) in Note [StaticEnv]
+contIsDupable (Select { sc_env = se }) = okToDupSE se -- ...ditto...
+contIsDupable (StrictBind { sc_env = se }) = okToDupSE se -- ...ditto...
+contIsDupable (StrictArg { sc_dup = dup }) = okToDup dup -- ...ditto...
+contIsDupable (CastIt { sc_cont = k }) = contIsDupable k
+contIsDupable (TickIt _ k) = contIsDupable k
-------------------
contIsTrivial :: SimplCont -> Bool
@@ -488,13 +510,11 @@ contHoleType :: SimplCont -> OutType
contHoleType (Stop ty _ _) = ty
contHoleType (TickIt _ k) = contHoleType k
contHoleType (CastIt { sc_co = co }) = coercionLKind co
-contHoleType (StrictBind { sc_bndr = b, sc_dup = dup, sc_env = se })
- = perhapsSubstTy dup se (idType b)
+contHoleType (StrictBind { sc_bndr = b, sc_env = se }) = perhapsSubstTy se (idType b)
contHoleType (StrictArg { sc_fun_ty = ty }) = funArgTy ty
contHoleType (ApplyToTy { sc_hole_ty = ty }) = ty -- See Note [The hole type in ApplyToTy]
contHoleType (ApplyToVal { sc_hole_ty = ty }) = ty -- See Note [The hole type in ApplyToTy]
-contHoleType (Select { sc_dup = d, sc_bndr = b, sc_env = se })
- = perhapsSubstTy d se (idType b)
+contHoleType (Select { sc_bndr = b, sc_env = se }) = perhapsSubstTy se (idType b)
-- Computes the multiplicity scaling factor at the hole. That is, in (case [] of
@@ -544,11 +564,11 @@ countValArgs (CastIt { sc_cont = cont }) = countValArgs cont
countValArgs _ = 0
-------------------
-contArgs :: SimplCont -> (Bool, [ArgSummary], SimplCont)
+contArgs :: SimplEnv -> SimplCont -> (Bool, [ArgSummary], SimplCont)
-- Summarises value args, discards type args and coercions
-- The returned continuation of the call is only used to
-- answer questions like "are you interesting?"
-contArgs cont
+contArgs env cont
| lone cont = (True, [], cont)
| otherwise = go [] cont
where
@@ -558,15 +578,11 @@ contArgs cont
lone _ = True
go args (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = k })
- = go (is_interesting arg se : args) k
+ = go (interestingArg env se arg : args) k
go args (ApplyToTy { sc_cont = k }) = go args k
go args (CastIt { sc_cont = k }) = go args k
go args k = (False, reverse args, k)
- is_interesting arg se = interestingArg se arg
- -- Do *not* use short-cutting substitution here
- -- because we want to get as much IdInfo as possible
-
contOutArgs :: SimplEnv -> SimplCont -> [OutExpr]
-- Get the leading arguments from the `SimplCont`, as /OutExprs/
contOutArgs env cont
@@ -577,9 +593,10 @@ contOutArgs env cont
go (ApplyToTy { sc_arg_ty = ty, sc_cont = cont })
= Type ty : go cont
- go (ApplyToVal { sc_dup = dup, sc_arg = arg, sc_env = env, sc_cont = cont })
- | isSimplified dup = arg : go cont
- | otherwise = GHC.Core.Subst.substExpr (getFullSubst in_scope env) arg : go cont
+ go (ApplyToVal { sc_arg = arg, sc_env = se, sc_cont = cont })
+ = case se of
+ Simplified {} -> arg : go cont
+ UnSimplified env -> GHC.Core.Subst.substExpr (getFullSubst in_scope env) arg : go cont
-- Make sure we apply the static environment `sc_env` as a substitution
-- to get an OutExpr. See (BF1) in Note [tryRules: plan (BEFORE)]
-- in GHC.Core.Opt.Simplify.Iteration
@@ -1055,9 +1072,12 @@ Wrinkles:
-}
-interestingArg :: SimplEnv -> CoreExpr -> ArgSummary
+interestingArg :: SimplEnv -> StaticEnv -> CoreExpr -> ArgSummary
-- See Note [Interesting arguments]
-interestingArg env e = go env 0 e
+interestingArg env se e
+ = case se of
+ Simplified {} -> go env 0 e
+ UnSimplified static_env -> go (static_env `setInScopeFromE` env) 0 e
where
-- n is # value args to which the expression is applied
go env n (Var v)
@@ -1565,13 +1585,13 @@ the former.
preInlineUnconditionally
:: SimplEnv -> TopLevelFlag -> InId
- -> DupFlag -> InExpr -> StaticEnv -- These three go together
+ -> InExpr -> StaticEnv -- These two go together
-> Maybe SimplEnv -- Returned env has extended substitution
-- Precondition: rhs satisfies the let-can-float invariant
-- See Note [Core let-can-float invariant] in GHC.Core
-- Reason: we don't want to inline single uses, or discard dead bindings,
-- for unlifted, side-effect-ful bindings
-preInlineUnconditionally env top_lvl bndr dup rhs rhs_env
+preInlineUnconditionally env top_lvl bndr rhs rhs_se
| not pre_inline_unconditionally = Nothing
| not active = Nothing
| isTopLevel top_lvl && isDeadEndId bndr = Nothing -- Note [Top-level bottoming Ids]
@@ -1593,8 +1613,9 @@ preInlineUnconditionally env top_lvl bndr dup rhs rhs_env
-- If not then ContEx
-- ToDo: flesh this note out
extend_subst_with inl_rhs
- | isSimplified dup = extendIdSubst env bndr $! DoneEx inl_rhs NotJoinPoint
- | otherwise = extendIdSubst env bndr $! mkContEx rhs_env inl_rhs
+ = case rhs_se of
+ Simplified _ -> extendIdSubst env bndr $! DoneEx inl_rhs NotJoinPoint
+ UnSimplified rhs_env -> extendIdSubst env bndr $! mkContEx rhs_env inl_rhs
one_occ IAmDead = True -- Happens in ((\x.1) v)
one_occ OneOcc{ occ_n_br = 1
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e8ac16f20c85840402906bbe683aab4…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e8ac16f20c85840402906bbe683aab4…
You're receiving this email because of your account on gitlab.haskell.org.
1
0