03 Jul '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
81ee62e0 by Alan Zimmerman at 2026-07-02T21:36:33-04:00
EPA: Remove LocatedLW from MatchGroup
This is the last usage of LocatedLW / SrcSpanAnnLW
- - - - -
32 changed files:
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/Types.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Tc/Gen/Arrow.hs
- compiler/GHC/Tc/Gen/Do.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Match.hs
- compiler/GHC/Tc/TyCl/PatSyn.hs
- compiler/GHC/ThToHs.hs
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/module/mod185.stderr
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/all.T
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- utils/check-exact/ExactPrint.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/81ee62e0b6bd8eda137d197ced3716b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/81ee62e0b6bd8eda137d197ced3716b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] Test driver: normalise line numbers into libraries
by Marge Bot (@marge-bot) 03 Jul '26
by Marge Bot (@marge-bot) 03 Jul '26
03 Jul '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
c6d53c16 by sheaf at 2026-07-02T21:35:44-04:00
Test driver: normalise line numbers into libraries
When comparing the stdout of tests that print out callstacks, we can't
rely on the stability of exact line:column spans pointing into libraries
(e.g. ghc-internal), as any change (such as adding a comment) can change
them.
This commit addresses this by normalising away line:column in callstacks,
but only when those point into internal libraries. We don't do this in
general, as the exact span might be important to the test (e.g. for a
span within the test module itself).
Fixes #27387
- - - - -
1 changed file:
- testsuite/driver/testlib.py
Changes:
=====================================
testsuite/driver/testlib.py
=====================================
@@ -2944,6 +2944,12 @@ def normalise_whitespace(s: str) -> str:
callSite_re = re.compile(r', called at (.+):[\d]+:[\d]+ in [<>\w\-\.]+:')
+# A line:column location pointing inside 'libraries' (e.g. ghc-internal).
+inLibrariesLoc_re = re.compile(
+ r'(libraries[\\/]\S+?)'
+ r':(?:\d+:\d+(?:-\d+)?|\(\d+,\d+\)-\(\d+,\d+\))' # line:col span
+)
+
def normalise_callstacks(s: str) -> str:
opts = getTestOpts()
def repl(matches):
@@ -2952,6 +2958,12 @@ def normalise_callstacks(s: str) -> str:
return ', called at {0}:<line>:<column> in <package-id>:'.format(location)
# Ignore line number differences in call stacks (#10834).
s = re.sub(callSite_re, repl, s)
+ # Ignore differences in line numbers pointing into internal libraries,
+ # as those line numbers are not stable (e.g. adding a comment somewhere
+ # in ghc-internal) (#27387).
+ s = re.sub(inLibrariesLoc_re,
+ lambda m: '{0}:<line>:<column>'.format(normalise_slashes_(m.group(1))),
+ s)
# Ignore the change in how we identify implicit call-stacks
s = s.replace('from ImplicitParams', 'from HasCallStack')
if not opts.keep_prof_callstacks:
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c6d53c1681d4afe7f6c637c3a34798f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c6d53c1681d4afe7f6c637c3a34798f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] 5 commits: Adjust releaseCapability_ precondition to allow cap->running_task == NULL
by Marge Bot (@marge-bot) 03 Jul '26
by Marge Bot (@marge-bot) 03 Jul '26
03 Jul '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
6e381626 by Duncan Coutts at 2026-07-01T22:29:55+01:00
Adjust releaseCapability_ precondition to allow cap->running_task == NULL
There are two use cases for releaseCapability_:
1. The current Task (cap->running_task) releases the Capability.
The Capability is marked free, and if there is any work to do,
an appropriate Task is woken up.
2. There is no current task (cap->task == NULL), and thus the
Capability is idle, and we want to wake up an idle Task to animate
the Capability. This case uses always_wakeup.
Currently, the precondition for releaseCapability_ is
cap->running_task != NULL
and so the 2nd use cases have to set cap->running_task (which is then
immediately overwritten) just to satisfy the precondition. See the
use cases in sendMessage and prodCapability.
So we can relax the precondition to be:
cap->running_task != NULL || always_wakeup
so that in the always_wakeup case, we say it is ok for the
cap->running_task to be NULL.
This lets us simplify sendMessage and prodCapability. In particular it
will allow prodCapability to not need a Task parameter.
The ulterior motive for all this is that I want to be able to call
prodCapability from an OS thread that is not itself a Task, in persuit
of issue #27086: disentangle I/O managers from wakeUpRts. The most
straightforward way to wake the RTS is using prodCapability, but the
context in which we will need to do that are threads that are not Tasks.
- - - - -
89404ebc by Duncan Coutts at 2026-07-01T22:29:55+01:00
prodCapability no longer needs to take a Task param
Now that releaseCapability_ can accept cap->running_task == NULL then it
is no longer necessary for prodCapability to require a Task.
- - - - -
4e60c5f6 by Duncan Coutts at 2026-07-01T22:29:56+01:00
Define prodOneCapability
There was an existing declaration for this in the header file, but no
definition.
Similarly, there is a declaration for prodAllCapabilities but no
definition, and we don't need it, so remove the declaration.
- - - - -
2527026f by Duncan Coutts at 2026-07-01T22:29:56+01:00
Add a wakeUpRtsViaTicker feature to the posix ticker
It proxies a call to wakeUpRts, but crucially, this can be called from
a signal handler context. It will be used for ctl-c handling.
- - - - -
aa5a03a5 by Duncan Coutts at 2026-07-01T22:29:56+01:00
Change how wakeUpRts works
Previously it would call wakeupIOManager to get a capability to wake up
and run. This works but it entangles the I/O managers with unrelated
features: ctl-c handling and idle gc (the two features that use wakeUpRts).
The reason it used wakeupIOManager is that this action is safe to use
from a posix signal handler, since it just posts bytes to a pipe.
Otherwise the more direct approach (used e.g. by sendMessage when the
target capability is idle) is to use releaseCapability. But that uses
condition variables and mutexes, which are not safe to use from within a
signal handler.
So instead of entangling the (multiple) I/O managers with this, we make
wakeUpRts use the direct approach (using prodOneCapability). On win32
the ctl-c console handler can call wakeUpRts directly, since it is
called in a proper thread. On posix, to deal with the signal handler
problem, we make the signal handler ask the ticker thread to proxy the
call to wakeUpRts, since the ticker thread is also a proper thread.
This will allow the I/O managers to no longer be concerned with this.
This is good because there are many I/O managers (and they're
complicated), but there is (on posix) only one ticker implementation. So
this is an overall reduction in coupling and complexity.
Fixes issue #27086
- - - - -
7 changed files:
- rts/Capability.c
- rts/Capability.h
- rts/Messages.c
- rts/Schedule.c
- rts/Ticker.h
- rts/posix/Ticker.c
- rts/sm/GC.c
Changes:
=====================================
rts/Capability.c
=====================================
@@ -525,13 +525,20 @@ giveCapabilityToTask (Capability *cap USED_IF_DEBUG, Task *task)
/* ----------------------------------------------------------------------------
* releaseCapability
*
- * The current Task (cap->task) releases the Capability. The Capability is
- * marked free, and if there is any work to do, an appropriate Task is woken up.
+ * This serves two purposes:
+ *
+ * 1. The current Task (cap->running_task) releases the Capability.
+ * The Capability is marked free, and if there is any work to do, an
+ * appropriate Task is woken up.
+ *
+ * 2. There is no current task (cap->task == NULL), and thus the Capability
+ * is idle, and we want to wake up an idle Task to animate the Capability.
+ * In this case set always_wakeup. See also prodCapability.
*
* The caller must hold cap->lock and will still hold it after
* releaseCapability returns.
*
- * N.B. May need to take all_tasks_mutex.
+ * N.B. May need to take all_tasks_mutex, if it needs to start a new task.
*
* ------------------------------------------------------------------------- */
@@ -540,12 +547,18 @@ void
releaseCapability_ (Capability* cap,
bool always_wakeup)
{
- Task *task;
-
- task = cap->running_task;
-
- ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task);
- ASSERT_RETURNING_TASKS(cap,task);
+ {
+ Task *task = cap->running_task;
+
+ ASSERT(task || always_wakeup);
+ // To cover purpose 2 above, we allow the cap->running_task to be
+ // NULL, to handle cases where a thread (that is not itself a Task)
+ // needs to wake up an idle task for the capability.
+ if (task) {
+ ASSERT_PARTIAL_CAPABILITY_INVARIANTS(cap,task);
+ ASSERT_RETURNING_TASKS(cap,task);
+ }
+ }
ASSERT_LOCK_HELD(&cap->lock);
RELAXED_STORE(&cap->running_task, NULL);
@@ -581,8 +594,8 @@ releaseCapability_ (Capability* cap,
// assertion is false: in schedule() we force a yield after
// ThreadBlocked, but the thread may be back on the run queue
// by now.
- task = peekRunQueue(cap)->bound->task;
- giveCapabilityToTask(cap, task);
+ Task *btask = peekRunQueue(cap)->bound->task;
+ giveCapabilityToTask(cap, btask);
return;
}
@@ -1087,16 +1100,25 @@ yieldCapability
#if defined(THREADED_RTS)
void
-prodCapability (Capability *cap, Task *task)
+prodCapability (Capability *cap)
{
ACQUIRE_LOCK(&cap->lock);
if (!cap->running_task) {
- cap->running_task = task;
releaseCapability_(cap,true);
}
RELEASE_LOCK(&cap->lock);
}
+/* Ensure at least one capability is not idle. Used to wake up the RTS
+ * in cases where we anticipate that all capabilities may be idle. In
+ * particular it is used for the ctl-c handler, and after the idle GC
+ * timeout to initiate idle GC. */
+void
+prodOneCapability (void)
+{
+ prodCapability(getCapability(0));
+}
+
#endif /* THREADED_RTS */
/* ----------------------------------------------------------------------------
=====================================
rts/Capability.h
=====================================
@@ -348,11 +348,7 @@ bool yieldCapability (Capability** pCap, Task *task, bool gcAllowed);
// need to service some global event.
//
void prodOneCapability (void);
-void prodCapability (Capability *cap, Task *task);
-
-// Similar to prodOneCapability(), but prods all of them.
-//
-void prodAllCapabilities (void);
+void prodCapability (Capability *cap);
// Attempt to gain control of a Capability if it is free.
//
=====================================
rts/Messages.c
=====================================
@@ -49,9 +49,11 @@ void sendMessage(Capability *from_cap, Capability *to_cap, Message *msg)
recordClosureMutated(from_cap,(StgClosure*)msg);
if (to_cap->running_task == NULL) {
- to_cap->running_task = myTask();
- // precond for releaseCapability_()
- releaseCapability_(to_cap,false);
+ /* Precond for releaseCapability_ is: running_task || always_wakeup.
+ * We have running_task == NULL, hence we must use always_wakeup. This
+ * is ok since the inbox is now non-empty, so we wake a task anyway.
+ */
+ releaseCapability_(to_cap, true /*always_wakeup*/);
} else {
interruptCapability(to_cap);
}
=====================================
rts/Schedule.c
=====================================
@@ -2885,8 +2885,8 @@ performBlockingMajorGC(void)
}
/* ---------------------------------------------------------------------------
- Interrupt execution.
- Might be called inside a signal handler so it mustn't do anything fancy.
+ Interrupt execution in response to ctl-c.
+ On posix, ctl-c is a signal, while on Win32 it is a console event.
------------------------------------------------------------------------ */
void
@@ -2896,17 +2896,37 @@ interruptStgRts(void)
setSchedState(SCHED_INTERRUPTING);
interruptAllCapabilities();
#if defined(THREADED_RTS)
+ /* It may be that all capabilities are idle. If so, we must wake one up. */
+#if defined(mingw32_HOST_OS)
+ /* On win32, console handlers are invoked in a proper thread, so we can
+ * directly call wakeUpRts. Although it is an OS thread, it is not one
+ * we created or control necessarily, so it may have no associated Task.
+ */
wakeUpRts();
+#else
+ /* On posix on the other hand, signal handlers are very limited in what
+ * they can do. We cannot directly call wakeUpRts below because it is not
+ * signal safe (it uses cond vars to wake up a task). So instead we proxy
+ * it: we interrupt the ticker thread and ask the ticker thread to call
+ * wakeUpRts below. The ticker thread is a proper thread and so can call
+ * wakeUpRts. We can interrupt the ticker thread from signal handler
+ * context safely because it only involves writing to a pipe/eventfd.
+ */
+ wakeUpRtsViaTicker();
+#endif
#endif
}
/* -----------------------------------------------------------------------------
Wake up the RTS
- This function causes at least one OS thread to wake up and run the
- scheduler loop. It is invoked when the RTS might be deadlocked, or
- an external event has arrived that may need servicing (eg. a
- keyboard interrupt).
+ This function causes at least one task to wake up and run the scheduler
+ loop on at least one capability.
+
+ It is invoked:
+ 1. as part of the idle GC scheme: when the RTS has been idle for long enough
+ and it is time to go back to the scheduler which will invoke idle GC; or
+ 2. when a ctl-c occurs (posix sigint signal or win32 console event)
In the single-threaded RTS we don't do anything here; we only have
one thread anyway, and the event that caused us to want to wake up
@@ -2916,10 +2936,11 @@ interruptStgRts(void)
#if defined(THREADED_RTS)
void wakeUpRts(void)
{
- // This forces the IO Manager thread to wakeup, which will
- // in turn ensure that some OS thread wakes up and runs the
- // scheduler loop, which will cause a GC and deadlock check.
- wakeupIOManager();
+ /* Our current thread may not have a Task, in particular it will not when
+ * called from interruptStgRts or via wakeUpRtsViaTicker. This is ok,
+ * prodOneCapability does not require one.
+ */
+ prodOneCapability();
}
#endif
=====================================
rts/Ticker.h
=====================================
@@ -52,4 +52,8 @@ void exitTicker(void);
void pauseTicker(void);
void unpauseTicker(void);
+#if defined(THREADED_RTS)
+void wakeUpRtsViaTicker(void);
+#endif
+
#include "EndPrivate.h"
=====================================
rts/posix/Ticker.c
=====================================
@@ -127,6 +127,13 @@ static Time ticker_interval = DEFAULT_TICK_INTERVAL;
// acknowledgement.
static bool pause_request;
+#if defined(THREADED_RTS)
+// Atomic variable used by the ctl-c handler (posix signal handler) to
+// communicate that the ticker thread should wake up the rts. This
+// communication is one-way, with no acknowledgement.
+static bool interrupt_request;
+#endif
+
// Atomic variable used by other threads to communicate that they want the
// ticker thread to exit.
static bool exit_request;
@@ -177,6 +184,13 @@ static void *ticker_thread_func(void *_handle_tick)
paused = ACQUIRE_LOAD_ALWAYS(&pause_request);
exit = RELAXED_LOAD_ALWAYS(&exit_request);
+
+#if defined(THREADED_RTS)
+ if (RELAXED_LOAD_ALWAYS(&interrupt_request)) {
+ RELEASE_STORE_ALWAYS(&interrupt_request, false);
+ wakeUpRts();
+ }
+#endif
} else if (errno != EINTR) {
// While the RTS attempts to mask signals, some foreign libraries
// that rely on signal delivery may unmask them. Consequently we
@@ -262,6 +276,14 @@ void pauseTicker(void)
sendFdWakeup(notifyfd_w);
}
+#if defined(THREADED_RTS)
+void wakeUpRtsViaTicker(void)
+{
+ RELAXED_STORE_ALWAYS(&interrupt_request, true);
+ sendFdWakeup(notifyfd_w);
+}
+#endif
+
/* Synchronous. Not idempotent.
* The ticker is guaranteed stopped after this.
*/
=====================================
rts/sm/GC.c
=====================================
@@ -1522,7 +1522,7 @@ waitForGcThreads (Capability *cap, bool idle_cap[])
for(i = 0; i < getNumCapabilities(); ++i) {
if (i == me || idle_cap[i]) { continue; }
if (SEQ_CST_LOAD(&gc_threads[i]->wakeup) != GC_THREAD_STANDING_BY) {
- prodCapability(getCapability(i), cap->running_task);
+ prodCapability(getCapability(i));
interruptCapability(getCapability(i));
}
}
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/8585f8cb561e0ac1a995e1fd45ee52…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/8585f8cb561e0ac1a995e1fd45ee52…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/az/exactprint-annotation-rationalisation] 2 commits: EPA: Remove LocatedP from CType
by Alan Zimmerman (@alanz) 03 Jul '26
by Alan Zimmerman (@alanz) 03 Jul '26
03 Jul '26
Alan Zimmerman pushed to branch wip/az/exactprint-annotation-rationalisation at Glasgow Haskell Compiler / GHC
Commits:
19cc63f2 by Alan Zimmerman at 2026-07-02T23:31:09+01:00
EPA: Remove LocatedP from CType
- - - - -
af438e12 by Alan Zimmerman at 2026-07-02T23:31:09+01:00
EPA: Remove LocatedP, last use in WarningTxt
- - - - -
12 changed files:
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Unit/Module/Warnings.hs
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
Changes:
=====================================
compiler/GHC/Builtin/Utils.hs
=====================================
@@ -299,7 +299,7 @@ ghcPrimWarns = WarnSome
[]
where
mk_txt msg =
- DeprecatedTxt NoSourceText [noLocA $ WithHsDocIdentifiers (StringLiteral NoSourceText msg Nothing) []]
+ DeprecatedTxt (NoSourceText, noAnn) [noLocA $ WithHsDocIdentifiers (StringLiteral NoSourceText msg Nothing) []]
mk_decl_dep (occ, msg) = (occ, mk_txt msg)
ghcPrimFixities :: [(OccName,Fixity)]
=====================================
compiler/GHC/Hs/Decls.hs
=====================================
@@ -1162,7 +1162,7 @@ cidDeprecation :: forall p. IsPass p
cidDeprecation = fmap unLoc . decl_deprecation (ghcPass @p)
where
decl_deprecation :: GhcPass p -> ClsInstDecl (GhcPass p)
- -> Maybe (LocatedP (WarningTxt (GhcPass p)))
+ -> Maybe (LocatedA (WarningTxt (GhcPass p)))
decl_deprecation GhcPs (ClsInstDecl{ cid_ext = (depr, _) } )
= depr
decl_deprecation GhcRn (ClsInstDecl{ cid_ext = depr })
@@ -1360,7 +1360,7 @@ derivDeprecation :: forall p. IsPass p
derivDeprecation = fmap unLoc . decl_deprecation (ghcPass @p)
where
decl_deprecation :: GhcPass p -> DerivDecl (GhcPass p)
- -> Maybe (LocatedP (WarningTxt (GhcPass p)))
+ -> Maybe (LocatedA (WarningTxt (GhcPass p)))
decl_deprecation GhcPs (DerivDecl{ deriv_ext = (depr, _) })
= depr
decl_deprecation GhcRn (DerivDecl{ deriv_ext = (depr, _) })
@@ -1701,7 +1701,7 @@ type instance Anno (FunDep (GhcPass p)) = SrcSpanAnnA
type instance Anno (FamilyResultSig (GhcPass p)) = EpAnnCO
type instance Anno (FamilyDecl (GhcPass p)) = SrcSpanAnnA
type instance Anno (InjectivityAnn (GhcPass p)) = EpAnnCO
-type instance Anno (CType (GhcPass p)) = SrcSpanAnnP
+type instance Anno (CType (GhcPass p)) = SrcSpanAnnA
type instance Anno (HsDerivingClause (GhcPass p)) = EpAnnCO
type instance Anno (DerivClauseTys (GhcPass _)) = SrcSpanAnnA
type instance Anno (StandaloneKindSig (GhcPass p)) = SrcSpanAnnA
=====================================
compiler/GHC/Hs/Dump.hs
=====================================
@@ -97,7 +97,6 @@ showAstData bs ba a0 = blankLine $$ showAstData' a0
`extQ` bagName `extQ` bagRdrName `extQ` bagVar `extQ` nameSet
`ext2Q` located
`extQ` srcSpanAnnA
- `extQ` srcSpanAnnP
`extQ` srcSpanAnnN
`extQ` srcSpanAnnBF
@@ -404,9 +403,6 @@ showAstData bs ba a0 = blankLine $$ showAstData' a0
srcSpanAnnA :: EpAnn [TrailingAnn] -> SDoc
srcSpanAnnA = locatedAnn'' (text "SrcSpanAnnA")
- srcSpanAnnP :: EpAnn AnnPragma -> SDoc
- srcSpanAnnP = locatedAnn'' (text "SrcSpanAnnP")
-
srcSpanAnnN :: EpAnn NameAnn -> SDoc
srcSpanAnnN = locatedAnn'' (text "SrcSpanAnnN")
=====================================
compiler/GHC/Iface/Syntax.hs
=====================================
@@ -83,7 +83,7 @@ import GHC.Core.TyCon ( Role (..), Injectivity(..), tyConBndrVisForAllTyFlag )
import GHC.Core.DataCon (SrcStrictness(..), SrcUnpackedness(..))
import GHC.Builtin.Types ( constraintKindTyConName )
import GHC.Stg.EnforceEpt.TagSig
-import GHC.Parser.Annotation (noLocA)
+import GHC.Parser.Annotation (noLocA, noAnn)
import GHC.Hs.Extension ( GhcPass, GhcRn, GhcTc )
import GHC.Hs.Decls.Overlap ( OverlapFlag )
import GHC.Hs.Doc ( WithHsDocIdentifiers(..) )
@@ -664,8 +664,8 @@ fromIfaceWarnings = \case
fromIfaceWarningTxt :: IfaceWarningTxt -> WarningTxt GhcRn
fromIfaceWarningTxt = \case
- IfWarningTxt src mb_cat strs -> WarningTxt src (noLocA . fromWarningCategory <$> mb_cat) (noLocA <$> map fromIfaceStringLiteralWithNames strs)
- IfDeprecatedTxt src strs -> DeprecatedTxt src (noLocA <$> map fromIfaceStringLiteralWithNames strs)
+ IfWarningTxt src mb_cat strs -> WarningTxt (src, noAnn) (noLocA . fromWarningCategory <$> mb_cat) (noLocA <$> map fromIfaceStringLiteralWithNames strs)
+ IfDeprecatedTxt src strs -> DeprecatedTxt (src, noAnn) (noLocA <$> map fromIfaceStringLiteralWithNames strs)
fromIfaceStringLiteralWithNames :: (IfaceStringLiteral, [IfExtName]) -> WithHsDocIdentifiers StringLiteral GhcRn
fromIfaceStringLiteralWithNames (str, names) = WithHsDocIdentifiers (fromIfaceStringLiteral str) (map noLoc names)
=====================================
compiler/GHC/Iface/Warnings.hs
=====================================
@@ -23,12 +23,11 @@ toIfaceWarnings (WarnSome vs ds) = IfWarnSome vs' ds'
ds' = [(occ, toIfaceWarningTxt txt) | (occ, txt) <- ds]
toIfaceWarningTxt :: WarningTxt GhcRn -> IfaceWarningTxt
-toIfaceWarningTxt (WarningTxt src mb_cat strs) = IfWarningTxt src (unLoc . iwc_wc . unLoc <$> mb_cat) (map (toIfaceStringLiteralWithNames . unLoc) strs)
-toIfaceWarningTxt (DeprecatedTxt src strs) = IfDeprecatedTxt src (map (toIfaceStringLiteralWithNames . unLoc) strs)
+toIfaceWarningTxt (WarningTxt (src, _) mb_cat strs) = IfWarningTxt src (unLoc . iwc_wc . unLoc <$> mb_cat) (map (toIfaceStringLiteralWithNames . unLoc) strs)
+toIfaceWarningTxt (DeprecatedTxt (src, _) strs) = IfDeprecatedTxt src (map (toIfaceStringLiteralWithNames . unLoc) strs)
toIfaceStringLiteralWithNames :: WithHsDocIdentifiers StringLiteral GhcRn -> (IfaceStringLiteral, [IfExtName])
toIfaceStringLiteralWithNames (WithHsDocIdentifiers src names) = (toIfaceStringLiteral src, map unLoc names)
toIfaceStringLiteral :: StringLiteral -> IfaceStringLiteral
toIfaceStringLiteral (StringLiteral sl fs _) = IfStringLiteral sl fs
-
=====================================
compiler/GHC/Parser.y
=====================================
@@ -1705,15 +1705,17 @@ datafam_inst_hdr :: { Located (Maybe (LHsContext GhcPs), HsOuterFamEqnTyVarBndrs
| type { sL1 $1 (Nothing, mkHsOuterImplicit, $1) }
-capi_ctype :: { Maybe (LocatedP (CType GhcPs)) }
+capi_ctype :: { Maybe (LocatedA (CType GhcPs)) }
capi_ctype : '{-# CTYPE' STRING STRING '#-}'
- {% fmap Just $ amsr (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $3) (Just (Header (getSTRINGs $2) (getSTRING $2)))
- (getSTRING $3)))
- (AnnPragma (glR $1) (epTok $4) noAnn (glR $2) (glR $3) noAnn noAnn) }
+ {% fmap Just $ amsA' (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $3)
+ (AnnPragma (glR $1) (epTok $4) noAnn (glR $2) (glR $3) noAnn noAnn)
+ (Just (Header (getSTRINGs $2) (getSTRING $2)))
+ (getSTRING $3)))}
| '{-# CTYPE' STRING '#-}'
- {% fmap Just $ amsr (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $2) Nothing (getSTRING $2)))
- (AnnPragma (glR $1) (epTok $3) noAnn noAnn (glR $2) noAnn noAnn) }
+ {% fmap Just $ amsA' (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $2)
+ (AnnPragma (glR $1) (epTok $3) noAnn noAnn (glR $2) noAnn noAnn)
+ Nothing (getSTRING $2)))}
| { Nothing }
@@ -2073,11 +2075,13 @@ to varid (used for rule_vars), 'checkRuleTyVarBndrNames' must be updated.
maybe_warning_pragma :: { Maybe (LWarningTxt GhcPs) }
: '{-# DEPRECATED' strings '#-}'
- {% fmap Just $ amsr (sLL $1 $> $ DeprecatedTxt (getDEPRECATED_PRAGs $1) (map stringLiteralToHsDocWst $ snd $ unLoc $2))
- (AnnPragma (glR $1) (epTok $3) (fst $ unLoc $2) noAnn noAnn noAnn noAnn) }
+ {% fmap Just $ amsA' (sLL $1 $> $
+ DeprecatedTxt (getDEPRECATED_PRAGs $1, AnnPragma (glR $1) (epTok $3) (fst $ unLoc $2) noAnn noAnn noAnn noAnn)
+ (map stringLiteralToHsDocWst $ snd $ unLoc $2))}
| '{-# WARNING' warning_category strings '#-}'
- {% fmap Just $ amsr (sLL $1 $> $ WarningTxt (getWARNING_PRAGs $1) $2 (map stringLiteralToHsDocWst $ snd $ unLoc $3))
- (AnnPragma (glR $1) (epTok $4) (fst $ unLoc $3) noAnn noAnn noAnn noAnn)}
+ {% fmap Just $ amsA' (sLL $1 $> $
+ WarningTxt (getWARNING_PRAGs $1, AnnPragma (glR $1) (epTok $4) (fst $ unLoc $3) noAnn noAnn noAnn noAnn)
+ $2 (map stringLiteralToHsDocWst $ snd $ unLoc $3))}
| {- empty -} { Nothing }
warning_category :: { Maybe (LocatedE (InWarningCategory GhcPs)) }
@@ -2106,7 +2110,7 @@ warning :: { OrdList (LWarnDecl GhcPs) }
: warning_category namespace_spec namelist strings
{% fmap unitOL $ amsA' (L (comb4 $1 $2 $3 $4)
(Warning (fst $ unLoc $4) (unLoc $2) (unLoc $3)
- (WarningTxt NoSourceText $1 (map stringLiteralToHsDocWst $ snd $ unLoc $4)))) }
+ (WarningTxt (NoSourceText, noAnn) $1 (map stringLiteralToHsDocWst $ snd $ unLoc $4)))) }
namespace_spec :: { Located (NamespaceSpecifier GhcPs) }
: 'type' { sL1 $1 $ TypeNamespaceSpecifier (epTok $1) }
@@ -2134,7 +2138,7 @@ deprecations :: { OrdList (LWarnDecl GhcPs) }
deprecation :: { OrdList (LWarnDecl GhcPs) }
: namespace_spec namelist strings
{% fmap unitOL $ amsA' (sL (comb3 $1 $2 $>) $ (Warning (fst $ unLoc $3) (unLoc $1) (unLoc $2)
- (DeprecatedTxt NoSourceText $ map stringLiteralToHsDocWst $ snd $ unLoc $3))) }
+ (DeprecatedTxt (NoSourceText, noAnn) $ map stringLiteralToHsDocWst $ snd $ unLoc $3))) }
strings :: { Located ((EpToken "[", EpToken "]"),[Located StringLiteral]) }
: STRING { sL1 $1 (noAnn,[L (gl $1) (getStringLiteral $1)]) }
=====================================
compiler/GHC/Parser/Annotation.hs
=====================================
@@ -27,9 +27,9 @@ module GHC.Parser.Annotation (
EpAnnCO,
-- ** Annotations in 'GenLocated'
- LocatedA, LocatedN, LocatedAn, LocatedP,
+ LocatedA, LocatedN, LocatedAn,
LocatedE, LocatedBF,
- SrcSpanAnnA, SrcSpanAnnP, SrcSpanAnnN,
+ SrcSpanAnnA, SrcSpanAnnN,
SrcSpanAnnBF,
-- ** Annotation data types used in 'GenLocated'
@@ -428,7 +428,6 @@ emptyComments = EpaComments []
type LocatedA = GenLocated SrcSpanAnnA
type LocatedN = GenLocated SrcSpanAnnN
-type LocatedP = GenLocated SrcSpanAnnP
type LocatedBF = GenLocated SrcSpanAnnBF
-- | Annotation for items appearing in a list. They can have one or
@@ -439,7 +438,6 @@ type SrcSpanAnnA = EpAnn [TrailingAnn]
-- on the context, such as backticks.
type SrcSpanAnnN = EpAnn NameAnn
-type SrcSpanAnnP = EpAnn AnnPragma
type SrcSpanAnnBF = EpAnn AnnBooleanFormula
type LocatedE = GenLocated EpaLocation
=====================================
compiler/GHC/Parser/PostProcess.hs
=====================================
@@ -229,7 +229,7 @@ mkClassDecl loc' (L _ (mcxt, tycl_hdr)) fds where_cls layout annsIn
mkTyData :: SrcSpan
-> Bool
-> NewOrData
- -> Maybe (LocatedP (CType GhcPs))
+ -> Maybe (LocatedA (CType GhcPs))
-> Located (Maybe (LHsContext GhcPs), LHsType GhcPs)
-> Maybe (LHsKind GhcPs)
-> [LConDecl GhcPs]
@@ -251,7 +251,7 @@ mkTyData loc' is_type_data new_or_data cType (L _ (mcxt, tycl_hdr))
tcdDataDefn = defn,
tcdModifiers = [] })) }
-mkDataDefn :: Maybe (LocatedP (CType GhcPs))
+mkDataDefn :: Maybe (LocatedA (CType GhcPs))
-> Maybe (LHsContext GhcPs)
-> Maybe (LHsKind GhcPs)
-> DataDefnCons (LConDecl GhcPs)
@@ -326,7 +326,7 @@ mkTyFamInstEqn loc bndrs lhs rhs annEq
mkDataFamInst :: SrcSpan
-> NewOrData
- -> Maybe (LocatedP (CType GhcPs))
+ -> Maybe (LocatedA (CType GhcPs))
-> (Maybe ( LHsContext GhcPs), HsOuterFamEqnTyVarBndrs GhcPs
, LHsType GhcPs)
-> Maybe (LHsKind GhcPs)
=====================================
compiler/GHC/Types/ForeignCall.hs
=====================================
@@ -109,6 +109,7 @@ import Data.Data (Data)
import Data.Functor ((<&>))
import Control.DeepSeq (NFData(..))
+import GHC.Parser.Annotation (AnnPragma, noAnn)
{-
************************************************************************
@@ -213,11 +214,11 @@ instance Outputable CCallSpec where
defaultCType :: String -> CType (GhcPass p)
defaultCType =
- CType (CTypeGhc NoSourceText NoSourceText) Nothing . fsLit
+ CType (CTypeGhc NoSourceText NoSourceText noAnn) Nothing . fsLit
-mkCType :: SourceText -> SourceText -> Maybe (Header (GhcPass p)) -> FastString -> CType (GhcPass p)
-mkCType x y m =
- CType (CTypeGhc x y) m
+mkCType :: SourceText -> SourceText -> AnnPragma -> Maybe (Header (GhcPass p)) -> FastString -> CType (GhcPass p)
+mkCType x y ann m =
+ CType (CTypeGhc x y ann) m
typeCheckCType :: CType GhcRn -> CType GhcTc
typeCheckCType (CType x y z) = CType x (typeCheckHeader <$> y) z
@@ -302,6 +303,7 @@ data StaticTargetGhc = StaticTargetGhc
data CTypeGhc = CTypeGhc
{ cTypeSourceText :: SourceText
, cTypeOtherText :: SourceText
+ , cTypeAnn :: AnnPragma
}
deriving (Data, Eq)
@@ -356,6 +358,7 @@ instance Binary CTypeGhc where
return $ CTypeGhc
{ cTypeSourceText = str1
, cTypeOtherText = str2
+ , cTypeAnn = noAnn
}
instance NFData StaticTargetGhc where
=====================================
compiler/GHC/Unit/Module/Warnings.hs
=====================================
@@ -156,8 +156,8 @@ warningTxtSame w1 w2
instance Outputable (InWarningCategory (GhcPass pass)) where
ppr (InWarningCategory _ wt) = text "in" <+> doubleQuotes (ppr wt)
-type instance XDeprecatedTxt (GhcPass _) = SourceText
-type instance XWarningTxt (GhcPass _) = SourceText
+type instance XDeprecatedTxt (GhcPass _) = (SourceText, AnnPragma)
+type instance XWarningTxt (GhcPass _) = (SourceText, AnnPragma)
type instance XXWarningTxt (GhcPass _) = DataConCantHappen
type instance XInWarningCategory (GhcPass _) = (EpToken "in", SourceText)
type instance XXInWarningCategory (GhcPass _) = DataConCantHappen
@@ -165,7 +165,7 @@ type instance XXInWarningCategory (GhcPass _) = DataConCantHappen
type instance Anno (WithHsDocIdentifiers StringLiteral pass) = EpaLocation
type instance Anno (InWarningCategory (GhcPass pass)) = EpaLocation
type instance Anno (WarningCategory) = EpaLocation
-type instance Anno (WarningTxt (GhcPass pass)) = SrcSpanAnnP
+type instance Anno (WarningTxt (GhcPass pass)) = SrcSpanAnnA
deriving stock instance Eq (WarningTxt GhcPs)
deriving stock instance Eq (WarningTxt GhcRn)
@@ -190,15 +190,15 @@ deriving instance Uniquable WarningCategory
instance Outputable (WarningTxt (GhcPass pass)) where
ppr (WarningTxt lsrc mcat ws)
= case lsrc of
- NoSourceText -> pp_ws ws
- SourceText src -> ftext src <+> ctg_doc <+> pp_ws ws <+> text "#-}"
+ (NoSourceText, _) -> pp_ws ws
+ (SourceText src, _) -> ftext src <+> ctg_doc <+> pp_ws ws <+> text "#-}"
where
ctg_doc = maybe empty (\ctg -> ppr ctg) mcat
ppr (DeprecatedTxt lsrc ds)
= case lsrc of
- NoSourceText -> pp_ws ds
- SourceText src -> ftext src <+> pp_ws ds <+> text "#-}"
+ (NoSourceText, _) -> pp_ws ds
+ (SourceText src, _) -> ftext src <+> pp_ws ds <+> text "#-}"
pp_ws :: [LocatedE (WithHsDocIdentifiers StringLiteral pass)] -> SDoc
pp_ws [l] = ppr $ unLoc l
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -1558,26 +1558,26 @@ instance ExactPrint ModuleName where
-- ---------------------------------------------------------------------
-instance ExactPrint (LocatedP (WarningTxt GhcPs)) where
- getAnnotationEntry = entryFromLocatedA
- setAnnotationAnchor = setAnchorAn
+instance ExactPrint (WarningTxt GhcPs) where
+ getAnnotationEntry _ = NoEntryVal
+ setAnnotationAnchor a _ _ _ = a
- exact (L (EpAnn l (AnnPragma o c (os,cs) l1 l2 t m) css) (WarningTxt src mb_cat ws)) = do
+ exact (WarningTxt (src, AnnPragma o c (os,cs) l1 l2 t m) mb_cat ws) = do
o' <- markAnnOpen'' o src "{-# WARNING"
mb_cat' <- markAnnotated mb_cat
os' <- markEpToken os
ws' <- mapM markAnnotated ws
cs' <- markEpToken cs
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' (os',cs') l1 l2 t m) css) (WarningTxt src mb_cat' ws'))
+ return (WarningTxt (src, AnnPragma o' c' (os',cs') l1 l2 t m) mb_cat' ws')
- exact (L (EpAnn l (AnnPragma o c (os,cs) l1 l2 t m) css) (DeprecatedTxt src ws)) = do
+ exact (DeprecatedTxt (src, AnnPragma o c (os,cs) l1 l2 t m) ws) = do
o' <- markAnnOpen'' o src "{-# DEPRECATED"
os' <- markEpToken os
ws' <- mapM markAnnotated ws
cs' <- markEpToken cs
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' (os',cs') l1 l2 t m) css) (DeprecatedTxt src ws'))
+ return (DeprecatedTxt (src, AnnPragma o' c' (os',cs') l1 l2 t m) ws')
instance Typeable p => ExactPrint (InWarningCategory (GhcPass p)) where
getAnnotationEntry _ = NoEntryVal
@@ -4407,13 +4407,14 @@ instance ExactPrint t => ExactPrint (HsModifierOf t GhcPs) where
-- ---------------------------------------------------------------------
-instance Typeable p => ExactPrint (LocatedP (CType (GhcPass p))) where
- getAnnotationEntry = entryFromLocatedA
- setAnnotationAnchor = setAnchorAn
+instance Typeable p => ExactPrint (CType (GhcPass p)) where
+ getAnnotationEntry _ = NoEntryVal
+ setAnnotationAnchor a _ _ _ = a
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (CType ext mh ct)) = do
+ exact (CType ext mh ct) = do
let stp = cTypeSourceText ext
stct = cTypeOtherText ext
+ AnnPragma o c s l1 l2 t m = cTypeAnn ext
o' <- markAnnOpen'' o stp "{-# CTYPE"
l1' <- case mh of
Nothing -> return l1
@@ -4421,7 +4422,7 @@ instance Typeable p => ExactPrint (LocatedP (CType (GhcPass p))) where
printStringAtAA l1 (toSourceTextWithSuffix srcH "" "")
l2' <- printStringAtAA l2 (toSourceTextWithSuffix stct (unpackFS ct) "")
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1' l2' t m) cs) (CType ext mh ct))
+ return (CType (ext { cTypeAnn = AnnPragma o' c' s l1' l2' t m }) mh ct)
-- ---------------------------------------------------------------------
=====================================
utils/haddock/haddock-api/src/Haddock/Types.hs
=====================================
@@ -835,7 +835,7 @@ type instance Anno (HsOuterTyVarBndrs Specificity DocNameI) = SrcSpanAnnA
type instance Anno (HsSigType DocNameI) = SrcSpanAnnA
type instance Anno (BooleanFormula DocNameI) = SrcSpanAnnBF
type instance Anno (OverlapMode DocNameI) = SrcSpanAnnA
-type instance Anno (CType DocNameI) = EpAnn AnnPragma
+type instance Anno (CType DocNameI) = SrcSpanAnnA
type instance Anno (Header DocNameI) = EpAnn AnnPragma
type instance Anno (HsModifierOf (LocatedA (HsType DocNameI)) DocNameI) = SrcSpanAnnA
type instance Anno (HsContextDetails DocNameI a) = SrcSpanAnnA
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cedb075fcd3d01509d7c3eed20039b…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cedb075fcd3d01509d7c3eed20039b…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/az/exactprint-annotation-rationalisation] 3 commits: EPA: Remove LocatedP from OverlapMode
by Alan Zimmerman (@alanz) 03 Jul '26
by Alan Zimmerman (@alanz) 03 Jul '26
03 Jul '26
Alan Zimmerman pushed to branch wip/az/exactprint-annotation-rationalisation at Glasgow Haskell Compiler / GHC
Commits:
3555aee5 by Alan Zimmerman at 2026-07-02T23:04:24+01:00
EPA: Remove LocatedP from OverlapMode
- - - - -
b7559a99 by Alan Zimmerman at 2026-07-02T23:04:24+01:00
EPA: Remove LocatedP from CType
- - - - -
cedb075f by Alan Zimmerman at 2026-07-02T23:04:24+01:00
EPA: Remove LocatedP, last use in WarningTxt
- - - - -
18 changed files:
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Decls/Overlap.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Unit/Module/Warnings.hs
- utils/check-exact/ExactPrint.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
Changes:
=====================================
compiler/GHC/Builtin/Utils.hs
=====================================
@@ -299,7 +299,7 @@ ghcPrimWarns = WarnSome
[]
where
mk_txt msg =
- DeprecatedTxt NoSourceText [noLocA $ WithHsDocIdentifiers (StringLiteral NoSourceText msg Nothing) []]
+ DeprecatedTxt (NoSourceText, noAnn) [noLocA $ WithHsDocIdentifiers (StringLiteral NoSourceText msg Nothing) []]
mk_decl_dep (occ, msg) = (occ, mk_txt msg)
ghcPrimFixities :: [(OccName,Fixity)]
=====================================
compiler/GHC/Hs/Decls.hs
=====================================
@@ -1162,7 +1162,7 @@ cidDeprecation :: forall p. IsPass p
cidDeprecation = fmap unLoc . decl_deprecation (ghcPass @p)
where
decl_deprecation :: GhcPass p -> ClsInstDecl (GhcPass p)
- -> Maybe (LocatedP (WarningTxt (GhcPass p)))
+ -> Maybe (LocatedA (WarningTxt (GhcPass p)))
decl_deprecation GhcPs (ClsInstDecl{ cid_ext = (depr, _) } )
= depr
decl_deprecation GhcRn (ClsInstDecl{ cid_ext = depr })
@@ -1272,20 +1272,25 @@ ppDerivStrategy mb =
Nothing -> empty
Just (L _ ds) -> ppr ds
-ppOverlapPragma :: Maybe (LocatedP (OverlapMode (GhcPass p))) -> SDoc
+ppOverlapPragma :: forall p. IsPass p => Maybe (LocatedA (OverlapMode (GhcPass p))) -> SDoc
ppOverlapPragma mb =
case mb of
Nothing -> empty
- Just (L _ (NoOverlap s)) -> maybe_stext s "{-# NO_OVERLAP #-}"
- Just (L _ (Overlappable s)) -> maybe_stext s "{-# OVERLAPPABLE #-}"
- Just (L _ (Overlapping s)) -> maybe_stext s "{-# OVERLAPPING #-}"
- Just (L _ (Overlaps s)) -> maybe_stext s "{-# OVERLAPS #-}"
- Just (L _ (Incoherent s)) -> maybe_stext s "{-# INCOHERENT #-}"
- Just (L _ (NonCanonical s)) -> maybe_stext s "{-# INCOHERENT #-}" -- No surface syntax for NONCANONICAL yet
+ Just (L _ (NoOverlap s)) -> maybe_stext (stext s) "{-# NO_OVERLAP #-}"
+ Just (L _ (Overlappable s)) -> maybe_stext (stext s) "{-# OVERLAPPABLE #-}"
+ Just (L _ (Overlapping s)) -> maybe_stext (stext s) "{-# OVERLAPPING #-}"
+ Just (L _ (Overlaps s)) -> maybe_stext (stext s) "{-# OVERLAPS #-}"
+ Just (L _ (Incoherent s)) -> maybe_stext (stext s) "{-# INCOHERENT #-}"
+ Just (L _ (NonCanonical s)) -> maybe_stext (stext s) "{-# INCOHERENT #-}" -- No surface syntax for NONCANONICAL yet
where
maybe_stext NoSourceText alt = text alt
maybe_stext (SourceText src) _ = ftext src <+> text "#-}"
+ stext :: XOverlapMode (GhcPass p) -> SourceText
+ stext s = case (ghcPass @p, s) of
+ (GhcPs, (s,_)) -> s
+ (GhcRn, (s,_)) -> s
+ (GhcTc, s) -> s
instance (OutputableBndrId p) => Outputable (InstDecl (GhcPass p)) where
ppr (ClsInstD { cid_inst = decl }) = ppr decl
@@ -1355,7 +1360,7 @@ derivDeprecation :: forall p. IsPass p
derivDeprecation = fmap unLoc . decl_deprecation (ghcPass @p)
where
decl_deprecation :: GhcPass p -> DerivDecl (GhcPass p)
- -> Maybe (LocatedP (WarningTxt (GhcPass p)))
+ -> Maybe (LocatedA (WarningTxt (GhcPass p)))
decl_deprecation GhcPs (DerivDecl{ deriv_ext = (depr, _) })
= depr
decl_deprecation GhcRn (DerivDecl{ deriv_ext = (depr, _) })
@@ -1696,7 +1701,7 @@ type instance Anno (FunDep (GhcPass p)) = SrcSpanAnnA
type instance Anno (FamilyResultSig (GhcPass p)) = EpAnnCO
type instance Anno (FamilyDecl (GhcPass p)) = SrcSpanAnnA
type instance Anno (InjectivityAnn (GhcPass p)) = EpAnnCO
-type instance Anno (CType (GhcPass p)) = SrcSpanAnnP
+type instance Anno (CType (GhcPass p)) = SrcSpanAnnA
type instance Anno (HsDerivingClause (GhcPass p)) = EpAnnCO
type instance Anno (DerivClauseTys (GhcPass _)) = SrcSpanAnnA
type instance Anno (StandaloneKindSig (GhcPass p)) = SrcSpanAnnA
@@ -1711,7 +1716,7 @@ type instance Anno (ClsInstDecl (GhcPass p)) = SrcSpanAnnA
type instance Anno (InstDecl (GhcPass p)) = SrcSpanAnnA
type instance Anno (DocDecl (GhcPass p)) = SrcSpanAnnA
type instance Anno (DerivDecl (GhcPass p)) = SrcSpanAnnA
-type instance Anno (OverlapMode (GhcPass p)) = SrcSpanAnnP
+type instance Anno (OverlapMode (GhcPass p)) = SrcSpanAnnA
type instance Anno (DerivStrategy (GhcPass p)) = EpAnnCO
type instance Anno (DefaultDecl (GhcPass p)) = SrcSpanAnnA
type instance Anno (ForeignDecl (GhcPass p)) = SrcSpanAnnA
=====================================
compiler/GHC/Hs/Decls/Overlap.hs
=====================================
@@ -31,6 +31,8 @@ import GHC.Prelude
import GHC.Hs.Extension
+import GHC.Parser.Annotation ( AnnPragma )
+
import Language.Haskell.Syntax.Decls.Overlap
import Language.Haskell.Syntax.Extension
@@ -70,11 +72,13 @@ instance NFData OverlapFlag where
instance Outputable OverlapFlag where
ppr flag = ppr (overlapMode flag) <+> pprSafeOverlap (isSafeOverlap flag)
-type instance XOverlapMode (GhcPass _) = SourceText
+type instance XOverlapMode GhcPs = (SourceText, AnnPragma)
+type instance XOverlapMode GhcRn = (SourceText, AnnPragma)
+type instance XOverlapMode GhcTc = SourceText
type instance XXOverlapMode (GhcPass _) = DataConCantHappen
-instance NFData (OverlapMode (GhcPass p)) where
+instance NFData (OverlapMode GhcTc) where
rnf = \case
NoOverlap s -> rnf s
Overlappable s -> rnf s
@@ -83,7 +87,7 @@ instance NFData (OverlapMode (GhcPass p)) where
Incoherent s -> rnf s
NonCanonical s -> rnf s
-instance Binary (OverlapMode (GhcPass p)) where
+instance Binary (OverlapMode GhcTc) where
put_ bh = \case
NoOverlap s -> putByte bh 0 >> put_ bh s
Overlaps s -> putByte bh 1 >> put_ bh s
=====================================
compiler/GHC/Hs/Dump.hs
=====================================
@@ -97,7 +97,6 @@ showAstData bs ba a0 = blankLine $$ showAstData' a0
`extQ` bagName `extQ` bagRdrName `extQ` bagVar `extQ` nameSet
`ext2Q` located
`extQ` srcSpanAnnA
- `extQ` srcSpanAnnP
`extQ` srcSpanAnnN
`extQ` srcSpanAnnBF
@@ -404,9 +403,6 @@ showAstData bs ba a0 = blankLine $$ showAstData' a0
srcSpanAnnA :: EpAnn [TrailingAnn] -> SDoc
srcSpanAnnA = locatedAnn'' (text "SrcSpanAnnA")
- srcSpanAnnP :: EpAnn AnnPragma -> SDoc
- srcSpanAnnP = locatedAnn'' (text "SrcSpanAnnP")
-
srcSpanAnnN :: EpAnn NameAnn -> SDoc
srcSpanAnnN = locatedAnn'' (text "SrcSpanAnnN")
=====================================
compiler/GHC/Iface/Ext/Ast.hs
=====================================
@@ -1750,7 +1750,7 @@ instance ToHie (RScoped (LocatedAn NoEpAnns (DerivStrategy GhcRn))) where
NewtypeStrategy _ -> []
ViaStrategy s -> [ toHie (TS (ResolvedScopes [sc]) s) ]
-instance ToHie (LocatedP (OverlapMode GhcRn)) where
+instance ToHie (LocatedA (OverlapMode GhcRn)) where
toHie (L span _) = locOnly (locA span)
instance ToHie (LocatedA (ConDecl GhcRn)) where
=====================================
compiler/GHC/Iface/Syntax.hs
=====================================
@@ -83,7 +83,7 @@ import GHC.Core.TyCon ( Role (..), Injectivity(..), tyConBndrVisForAllTyFlag )
import GHC.Core.DataCon (SrcStrictness(..), SrcUnpackedness(..))
import GHC.Builtin.Types ( constraintKindTyConName )
import GHC.Stg.EnforceEpt.TagSig
-import GHC.Parser.Annotation (noLocA)
+import GHC.Parser.Annotation (noLocA, noAnn)
import GHC.Hs.Extension ( GhcPass, GhcRn, GhcTc )
import GHC.Hs.Decls.Overlap ( OverlapFlag )
import GHC.Hs.Doc ( WithHsDocIdentifiers(..) )
@@ -664,8 +664,8 @@ fromIfaceWarnings = \case
fromIfaceWarningTxt :: IfaceWarningTxt -> WarningTxt GhcRn
fromIfaceWarningTxt = \case
- IfWarningTxt src mb_cat strs -> WarningTxt src (noLocA . fromWarningCategory <$> mb_cat) (noLocA <$> map fromIfaceStringLiteralWithNames strs)
- IfDeprecatedTxt src strs -> DeprecatedTxt src (noLocA <$> map fromIfaceStringLiteralWithNames strs)
+ IfWarningTxt src mb_cat strs -> WarningTxt (src, noAnn) (noLocA . fromWarningCategory <$> mb_cat) (noLocA <$> map fromIfaceStringLiteralWithNames strs)
+ IfDeprecatedTxt src strs -> DeprecatedTxt (src, noAnn) (noLocA <$> map fromIfaceStringLiteralWithNames strs)
fromIfaceStringLiteralWithNames :: (IfaceStringLiteral, [IfExtName]) -> WithHsDocIdentifiers StringLiteral GhcRn
fromIfaceStringLiteralWithNames (str, names) = WithHsDocIdentifiers (fromIfaceStringLiteral str) (map noLoc names)
=====================================
compiler/GHC/Iface/Warnings.hs
=====================================
@@ -23,12 +23,11 @@ toIfaceWarnings (WarnSome vs ds) = IfWarnSome vs' ds'
ds' = [(occ, toIfaceWarningTxt txt) | (occ, txt) <- ds]
toIfaceWarningTxt :: WarningTxt GhcRn -> IfaceWarningTxt
-toIfaceWarningTxt (WarningTxt src mb_cat strs) = IfWarningTxt src (unLoc . iwc_wc . unLoc <$> mb_cat) (map (toIfaceStringLiteralWithNames . unLoc) strs)
-toIfaceWarningTxt (DeprecatedTxt src strs) = IfDeprecatedTxt src (map (toIfaceStringLiteralWithNames . unLoc) strs)
+toIfaceWarningTxt (WarningTxt (src, _) mb_cat strs) = IfWarningTxt src (unLoc . iwc_wc . unLoc <$> mb_cat) (map (toIfaceStringLiteralWithNames . unLoc) strs)
+toIfaceWarningTxt (DeprecatedTxt (src, _) strs) = IfDeprecatedTxt src (map (toIfaceStringLiteralWithNames . unLoc) strs)
toIfaceStringLiteralWithNames :: WithHsDocIdentifiers StringLiteral GhcRn -> (IfaceStringLiteral, [IfExtName])
toIfaceStringLiteralWithNames (WithHsDocIdentifiers src names) = (toIfaceStringLiteral src, map unLoc names)
toIfaceStringLiteral :: StringLiteral -> IfaceStringLiteral
toIfaceStringLiteral (StringLiteral sl fs _) = IfStringLiteral sl fs
-
=====================================
compiler/GHC/Parser.y
=====================================
@@ -1469,15 +1469,15 @@ inst_decl :: { LInstDecl GhcPs }
(fmap reverse $7)
(AnnDataDefn [] [] NoEpTok tnewtype tdata (epTok $2) dcolon twhere oc cc NoEpTok)}}
-overlap_pragma :: { Maybe (LocatedP (OverlapMode GhcPs)) }
- : '{-# OVERLAPPABLE' '#-}' {% fmap Just $ amsr (sLL $1 $> (Overlappable (getOVERLAPPABLE_PRAGs $1)))
- (AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn) }
- | '{-# OVERLAPPING' '#-}' {% fmap Just $ amsr (sLL $1 $> (Overlapping (getOVERLAPPING_PRAGs $1)))
- (AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn) }
- | '{-# OVERLAPS' '#-}' {% fmap Just $ amsr (sLL $1 $> (Overlaps (getOVERLAPS_PRAGs $1)))
- (AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn) }
- | '{-# INCOHERENT' '#-}' {% fmap Just $ amsr (sLL $1 $> (Incoherent (getINCOHERENT_PRAGs $1)))
- (AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn) }
+overlap_pragma :: { Maybe (LocatedA (OverlapMode GhcPs)) }
+ : '{-# OVERLAPPABLE' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Overlappable (getOVERLAPPABLE_PRAGs $1,
+ AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) }
+ | '{-# OVERLAPPING' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Overlapping (getOVERLAPPING_PRAGs $1,
+ AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) }
+ | '{-# OVERLAPS' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Overlaps (getOVERLAPS_PRAGs $1,
+ AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) }
+ | '{-# INCOHERENT' '#-}' {% fmap Just $ amsA' (sLL $1 $> (Incoherent (getINCOHERENT_PRAGs $1,
+ AnnPragma (glR $1) (epTok $2) noAnn noAnn noAnn noAnn noAnn))) }
| {- empty -} { Nothing }
deriv_strategy_no_via :: { LDerivStrategy GhcPs }
@@ -1705,15 +1705,17 @@ datafam_inst_hdr :: { Located (Maybe (LHsContext GhcPs), HsOuterFamEqnTyVarBndrs
| type { sL1 $1 (Nothing, mkHsOuterImplicit, $1) }
-capi_ctype :: { Maybe (LocatedP (CType GhcPs)) }
+capi_ctype :: { Maybe (LocatedA (CType GhcPs)) }
capi_ctype : '{-# CTYPE' STRING STRING '#-}'
- {% fmap Just $ amsr (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $3) (Just (Header (getSTRINGs $2) (getSTRING $2)))
- (getSTRING $3)))
- (AnnPragma (glR $1) (epTok $4) noAnn (glR $2) (glR $3) noAnn noAnn) }
+ {% fmap Just $ amsA' (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $3)
+ (AnnPragma (glR $1) (epTok $4) noAnn (glR $2) (glR $3) noAnn noAnn)
+ (Just (Header (getSTRINGs $2) (getSTRING $2)))
+ (getSTRING $3)))}
| '{-# CTYPE' STRING '#-}'
- {% fmap Just $ amsr (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $2) Nothing (getSTRING $2)))
- (AnnPragma (glR $1) (epTok $3) noAnn noAnn (glR $2) noAnn noAnn) }
+ {% fmap Just $ amsA' (sLL $1 $> (mkCType (getCTYPEs $1) (getSTRINGs $2)
+ (AnnPragma (glR $1) (epTok $3) noAnn noAnn (glR $2) noAnn noAnn)
+ Nothing (getSTRING $2)))}
| { Nothing }
@@ -2073,11 +2075,13 @@ to varid (used for rule_vars), 'checkRuleTyVarBndrNames' must be updated.
maybe_warning_pragma :: { Maybe (LWarningTxt GhcPs) }
: '{-# DEPRECATED' strings '#-}'
- {% fmap Just $ amsr (sLL $1 $> $ DeprecatedTxt (getDEPRECATED_PRAGs $1) (map stringLiteralToHsDocWst $ snd $ unLoc $2))
- (AnnPragma (glR $1) (epTok $3) (fst $ unLoc $2) noAnn noAnn noAnn noAnn) }
+ {% fmap Just $ amsA' (sLL $1 $> $
+ DeprecatedTxt (getDEPRECATED_PRAGs $1, AnnPragma (glR $1) (epTok $3) (fst $ unLoc $2) noAnn noAnn noAnn noAnn)
+ (map stringLiteralToHsDocWst $ snd $ unLoc $2))}
| '{-# WARNING' warning_category strings '#-}'
- {% fmap Just $ amsr (sLL $1 $> $ WarningTxt (getWARNING_PRAGs $1) $2 (map stringLiteralToHsDocWst $ snd $ unLoc $3))
- (AnnPragma (glR $1) (epTok $4) (fst $ unLoc $3) noAnn noAnn noAnn noAnn)}
+ {% fmap Just $ amsA' (sLL $1 $> $
+ WarningTxt (getWARNING_PRAGs $1, AnnPragma (glR $1) (epTok $4) (fst $ unLoc $3) noAnn noAnn noAnn noAnn)
+ $2 (map stringLiteralToHsDocWst $ snd $ unLoc $3))}
| {- empty -} { Nothing }
warning_category :: { Maybe (LocatedE (InWarningCategory GhcPs)) }
@@ -2106,7 +2110,7 @@ warning :: { OrdList (LWarnDecl GhcPs) }
: warning_category namespace_spec namelist strings
{% fmap unitOL $ amsA' (L (comb4 $1 $2 $3 $4)
(Warning (fst $ unLoc $4) (unLoc $2) (unLoc $3)
- (WarningTxt NoSourceText $1 (map stringLiteralToHsDocWst $ snd $ unLoc $4)))) }
+ (WarningTxt (NoSourceText, noAnn) $1 (map stringLiteralToHsDocWst $ snd $ unLoc $4)))) }
namespace_spec :: { Located (NamespaceSpecifier GhcPs) }
: 'type' { sL1 $1 $ TypeNamespaceSpecifier (epTok $1) }
@@ -2134,7 +2138,7 @@ deprecations :: { OrdList (LWarnDecl GhcPs) }
deprecation :: { OrdList (LWarnDecl GhcPs) }
: namespace_spec namelist strings
{% fmap unitOL $ amsA' (sL (comb3 $1 $2 $>) $ (Warning (fst $ unLoc $3) (unLoc $1) (unLoc $2)
- (DeprecatedTxt NoSourceText $ map stringLiteralToHsDocWst $ snd $ unLoc $3))) }
+ (DeprecatedTxt (NoSourceText, noAnn) $ map stringLiteralToHsDocWst $ snd $ unLoc $3))) }
strings :: { Located ((EpToken "[", EpToken "]"),[Located StringLiteral]) }
: STRING { sL1 $1 (noAnn,[L (gl $1) (getStringLiteral $1)]) }
=====================================
compiler/GHC/Parser/Annotation.hs
=====================================
@@ -27,9 +27,9 @@ module GHC.Parser.Annotation (
EpAnnCO,
-- ** Annotations in 'GenLocated'
- LocatedA, LocatedN, LocatedAn, LocatedP,
+ LocatedA, LocatedN, LocatedAn,
LocatedE, LocatedBF,
- SrcSpanAnnA, SrcSpanAnnP, SrcSpanAnnN,
+ SrcSpanAnnA, SrcSpanAnnN,
SrcSpanAnnBF,
-- ** Annotation data types used in 'GenLocated'
@@ -428,7 +428,6 @@ emptyComments = EpaComments []
type LocatedA = GenLocated SrcSpanAnnA
type LocatedN = GenLocated SrcSpanAnnN
-type LocatedP = GenLocated SrcSpanAnnP
type LocatedBF = GenLocated SrcSpanAnnBF
-- | Annotation for items appearing in a list. They can have one or
@@ -439,7 +438,6 @@ type SrcSpanAnnA = EpAnn [TrailingAnn]
-- on the context, such as backticks.
type SrcSpanAnnN = EpAnn NameAnn
-type SrcSpanAnnP = EpAnn AnnPragma
type SrcSpanAnnBF = EpAnn AnnBooleanFormula
type LocatedE = GenLocated EpaLocation
=====================================
compiler/GHC/Parser/PostProcess.hs
=====================================
@@ -229,7 +229,7 @@ mkClassDecl loc' (L _ (mcxt, tycl_hdr)) fds where_cls layout annsIn
mkTyData :: SrcSpan
-> Bool
-> NewOrData
- -> Maybe (LocatedP (CType GhcPs))
+ -> Maybe (LocatedA (CType GhcPs))
-> Located (Maybe (LHsContext GhcPs), LHsType GhcPs)
-> Maybe (LHsKind GhcPs)
-> [LConDecl GhcPs]
@@ -251,7 +251,7 @@ mkTyData loc' is_type_data new_or_data cType (L _ (mcxt, tycl_hdr))
tcdDataDefn = defn,
tcdModifiers = [] })) }
-mkDataDefn :: Maybe (LocatedP (CType GhcPs))
+mkDataDefn :: Maybe (LocatedA (CType GhcPs))
-> Maybe (LHsContext GhcPs)
-> Maybe (LHsKind GhcPs)
-> DataDefnCons (LConDecl GhcPs)
@@ -326,7 +326,7 @@ mkTyFamInstEqn loc bndrs lhs rhs annEq
mkDataFamInst :: SrcSpan
-> NewOrData
- -> Maybe (LocatedP (CType GhcPs))
+ -> Maybe (LocatedA (CType GhcPs))
-> (Maybe ( LHsContext GhcPs), HsOuterFamEqnTyVarBndrs GhcPs
, LHsType GhcPs)
-> Maybe (LHsKind GhcPs)
=====================================
compiler/GHC/Tc/Deriv.hs
=====================================
@@ -11,7 +11,7 @@
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
-- | Handles @deriving@ clauses on @data@ declarations.
-module GHC.Tc.Deriv ( tcDeriving, DerivInfo(..) ) where
+module GHC.Tc.Deriv ( tcDeriving, DerivInfo(..), tcOverlapMode ) where
import GHC.Prelude
@@ -776,12 +776,12 @@ deriveStandalone (L loc (DerivDecl (warn, _) deriv_ty mb_lderiv_strat overlap_mo
tcOverlapMode :: OverlapMode GhcRn -> OverlapMode GhcTc
tcOverlapMode = \case
- NoOverlap s -> NoOverlap s
- Overlappable s -> Overlappable s
- Overlapping s -> Overlapping s
- Overlaps s -> Overlaps s
- Incoherent s -> Incoherent s
- NonCanonical s -> NonCanonical s
+ NoOverlap s -> NoOverlap (fst s)
+ Overlappable s -> Overlappable (fst s)
+ Overlapping s -> Overlapping (fst s)
+ Overlaps s -> Overlaps (fst s)
+ Incoherent s -> Incoherent (fst s)
+ NonCanonical s -> NonCanonical (fst s)
-- Typecheck the type in a standalone deriving declaration.
--
=====================================
compiler/GHC/Tc/TyCl/Instance.hs
=====================================
@@ -559,7 +559,7 @@ tcClsInstDecl (L loc (ClsInstDecl { cid_ext = lwarn
-- Dfun location is that of instance *header*
; let warn = fmap unLoc lwarn
- ; ispec <- newClsInst (fmap unLoc overlap_mode) dfun_name
+ ; ispec <- newClsInst (fmap (tcOverlapMode . unLoc) overlap_mode) dfun_name
tyvars theta clas inst_tys warn
; let inst_binds = InstBindings
=====================================
compiler/GHC/Tc/Utils/Instantiate.hs
=====================================
@@ -905,7 +905,7 @@ hasFixedRuntimeRepRes std_nm user_expr ty = mapM_ do_check mb_arity
************************************************************************
-}
-getOverlapFlag :: Maybe (OverlapMode (GhcPass p)) -- User pragma if any
+getOverlapFlag :: Maybe (OverlapMode GhcTc) -- User pragma if any
-> TcM OverlapFlag
-- Construct the OverlapFlag from the global module flags,
-- but if the overlap_mode argument is (Just m),
@@ -929,9 +929,9 @@ getOverlapFlag overlap_mode_prag
overlap_mode
| Just m <- overlap_mode_prag = m
- | incoherent_ok = Incoherent NoSourceText
- | overlap_ok = Overlaps NoSourceText
- | otherwise = NoOverlap NoSourceText
+ | incoherent_ok = Incoherent noAnn
+ | overlap_ok = Overlaps noAnn
+ | otherwise = NoOverlap noAnn
-- final_overlap_mode: the `-fspecialise-incoherents` flag controls the
-- meaning of the `Incoherent` overlap mode: as either an Incoherent overlap
@@ -957,7 +957,7 @@ tcGetInsts :: TcM [ClsInst]
-- Gets the local class instances.
tcGetInsts = fmap tcg_insts getGblEnv
-newClsInst :: Maybe (OverlapMode (GhcPass p)) -- User pragma
+newClsInst :: Maybe (OverlapMode GhcTc) -- User pragma
-> Name -> [TyVar] -> ThetaType
-> Class -> [Type] -> Maybe (WarningTxt GhcRn) -> TcM ClsInst
newClsInst overlap_mode dfun_name tvs theta clas tys warn
=====================================
compiler/GHC/ThToHs.hs
=====================================
@@ -337,7 +337,6 @@ cvtDec (ClassD ctxt cl tvs fds decs)
}
cvtDec (InstanceD o ctxt ty decs)
- -- = do { (binds', sigs', fams', ats', adts') <- cvt_ci_decs InstanceDecl decs
= do { decs' <- cvt_ci_decs InstanceDecl decs
; let (fams', decls') = partitionWith is_fam_decl decs'
; for_ (nonEmpty fams') $ \ bad_fams ->
@@ -356,10 +355,10 @@ cvtDec (InstanceD o ctxt ty decs)
where
overlap pragma =
case pragma of
- TH.Overlaps -> Hs.Overlaps (SourceText $ fsLit "{-# OVERLAPS")
- TH.Overlappable -> Hs.Overlappable (SourceText $ fsLit "{-# OVERLAPPABLE")
- TH.Overlapping -> Hs.Overlapping (SourceText $ fsLit "{-# OVERLAPPING")
- TH.Incoherent -> Hs.Incoherent (SourceText $ fsLit "{-# INCOHERENT")
+ TH.Overlaps -> Hs.Overlaps (SourceText $ fsLit "{-# OVERLAPS", noAnn)
+ TH.Overlappable -> Hs.Overlappable (SourceText $ fsLit "{-# OVERLAPPABLE", noAnn)
+ TH.Overlapping -> Hs.Overlapping (SourceText $ fsLit "{-# OVERLAPPING", noAnn)
+ TH.Incoherent -> Hs.Incoherent (SourceText $ fsLit "{-# INCOHERENT", noAnn)
=====================================
compiler/GHC/Types/ForeignCall.hs
=====================================
@@ -109,6 +109,7 @@ import Data.Data (Data)
import Data.Functor ((<&>))
import Control.DeepSeq (NFData(..))
+import GHC.Parser.Annotation (AnnPragma, noAnn)
{-
************************************************************************
@@ -213,11 +214,11 @@ instance Outputable CCallSpec where
defaultCType :: String -> CType (GhcPass p)
defaultCType =
- CType (CTypeGhc NoSourceText NoSourceText) Nothing . fsLit
+ CType (CTypeGhc NoSourceText NoSourceText noAnn) Nothing . fsLit
-mkCType :: SourceText -> SourceText -> Maybe (Header (GhcPass p)) -> FastString -> CType (GhcPass p)
-mkCType x y m =
- CType (CTypeGhc x y) m
+mkCType :: SourceText -> SourceText -> AnnPragma -> Maybe (Header (GhcPass p)) -> FastString -> CType (GhcPass p)
+mkCType x y ann m =
+ CType (CTypeGhc x y ann) m
typeCheckCType :: CType GhcRn -> CType GhcTc
typeCheckCType (CType x y z) = CType x (typeCheckHeader <$> y) z
@@ -302,6 +303,7 @@ data StaticTargetGhc = StaticTargetGhc
data CTypeGhc = CTypeGhc
{ cTypeSourceText :: SourceText
, cTypeOtherText :: SourceText
+ , cTypeAnn :: AnnPragma
}
deriving (Data, Eq)
@@ -350,12 +352,15 @@ instance Binary CTypeGhc where
put_ bh ct = do
put_ bh (cTypeSourceText ct)
put_ bh (cTypeOtherText ct)
+ put_ bh (cTypeAnn ct)
get bh = do
str1 <- get bh
str2 <- get bh
+ ann <- get bh
return $ CTypeGhc
{ cTypeSourceText = str1
, cTypeOtherText = str2
+ , cTypeAnn = ann
}
instance NFData StaticTargetGhc where
=====================================
compiler/GHC/Unit/Module/Warnings.hs
=====================================
@@ -156,8 +156,8 @@ warningTxtSame w1 w2
instance Outputable (InWarningCategory (GhcPass pass)) where
ppr (InWarningCategory _ wt) = text "in" <+> doubleQuotes (ppr wt)
-type instance XDeprecatedTxt (GhcPass _) = SourceText
-type instance XWarningTxt (GhcPass _) = SourceText
+type instance XDeprecatedTxt (GhcPass _) = (SourceText, AnnPragma)
+type instance XWarningTxt (GhcPass _) = (SourceText, AnnPragma)
type instance XXWarningTxt (GhcPass _) = DataConCantHappen
type instance XInWarningCategory (GhcPass _) = (EpToken "in", SourceText)
type instance XXInWarningCategory (GhcPass _) = DataConCantHappen
@@ -165,7 +165,7 @@ type instance XXInWarningCategory (GhcPass _) = DataConCantHappen
type instance Anno (WithHsDocIdentifiers StringLiteral pass) = EpaLocation
type instance Anno (InWarningCategory (GhcPass pass)) = EpaLocation
type instance Anno (WarningCategory) = EpaLocation
-type instance Anno (WarningTxt (GhcPass pass)) = SrcSpanAnnP
+type instance Anno (WarningTxt (GhcPass pass)) = SrcSpanAnnA
deriving stock instance Eq (WarningTxt GhcPs)
deriving stock instance Eq (WarningTxt GhcRn)
@@ -190,15 +190,15 @@ deriving instance Uniquable WarningCategory
instance Outputable (WarningTxt (GhcPass pass)) where
ppr (WarningTxt lsrc mcat ws)
= case lsrc of
- NoSourceText -> pp_ws ws
- SourceText src -> ftext src <+> ctg_doc <+> pp_ws ws <+> text "#-}"
+ (NoSourceText, _) -> pp_ws ws
+ (SourceText src, _) -> ftext src <+> ctg_doc <+> pp_ws ws <+> text "#-}"
where
ctg_doc = maybe empty (\ctg -> ppr ctg) mcat
ppr (DeprecatedTxt lsrc ds)
= case lsrc of
- NoSourceText -> pp_ws ds
- SourceText src -> ftext src <+> pp_ws ds <+> text "#-}"
+ (NoSourceText, _) -> pp_ws ds
+ (SourceText src, _) -> ftext src <+> pp_ws ds <+> text "#-}"
pp_ws :: [LocatedE (WithHsDocIdentifiers StringLiteral pass)] -> SDoc
pp_ws [l] = ppr $ unLoc l
=====================================
utils/check-exact/ExactPrint.hs
=====================================
@@ -1558,26 +1558,26 @@ instance ExactPrint ModuleName where
-- ---------------------------------------------------------------------
-instance ExactPrint (LocatedP (WarningTxt GhcPs)) where
- getAnnotationEntry = entryFromLocatedA
- setAnnotationAnchor = setAnchorAn
+instance ExactPrint (WarningTxt GhcPs) where
+ getAnnotationEntry _ = NoEntryVal
+ setAnnotationAnchor a _ _ _ = a
- exact (L (EpAnn l (AnnPragma o c (os,cs) l1 l2 t m) css) (WarningTxt src mb_cat ws)) = do
+ exact (WarningTxt (src, AnnPragma o c (os,cs) l1 l2 t m) mb_cat ws) = do
o' <- markAnnOpen'' o src "{-# WARNING"
mb_cat' <- markAnnotated mb_cat
os' <- markEpToken os
ws' <- mapM markAnnotated ws
cs' <- markEpToken cs
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' (os',cs') l1 l2 t m) css) (WarningTxt src mb_cat' ws'))
+ return (WarningTxt (src, AnnPragma o' c' (os',cs') l1 l2 t m) mb_cat' ws')
- exact (L (EpAnn l (AnnPragma o c (os,cs) l1 l2 t m) css) (DeprecatedTxt src ws)) = do
+ exact (DeprecatedTxt (src, AnnPragma o c (os,cs) l1 l2 t m) ws) = do
o' <- markAnnOpen'' o src "{-# DEPRECATED"
os' <- markEpToken os
ws' <- mapM markAnnotated ws
cs' <- markEpToken cs
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' (os',cs') l1 l2 t m) css) (DeprecatedTxt src ws'))
+ return (DeprecatedTxt (src, AnnPragma o' c' (os',cs') l1 l2 t m) ws')
instance Typeable p => ExactPrint (InWarningCategory (GhcPass p)) where
getAnnotationEntry _ = NoEntryVal
@@ -2248,40 +2248,40 @@ instance ExactPrint (TyFamInstDecl GhcPs) where
-- ---------------------------------------------------------------------
-instance Typeable p => ExactPrint (LocatedP (OverlapMode (GhcPass p))) where
- getAnnotationEntry = entryFromLocatedA
- setAnnotationAnchor = setAnchorAn
+instance ExactPrint (OverlapMode GhcPs) where
+ getAnnotationEntry _ = NoEntryVal
+ setAnnotationAnchor a _ _ _ = a
-- NOTE: NoOverlap is only used in the typechecker
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (NoOverlap src)) = do
+ exact (NoOverlap (src, AnnPragma o c s l1 l2 t m)) = do
o' <- markAnnOpen'' o src "{-# NO_OVERLAP"
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1 l2 t m) cs) (NoOverlap src))
+ return (NoOverlap (src, AnnPragma o' c' s l1 l2 t m))
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (Overlappable src)) = do
+ exact (Overlappable (src, AnnPragma o c s l1 l2 t m)) = do
o' <- markAnnOpen'' o src "{-# OVERLAPPABLE"
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1 l2 t m) cs) (Overlappable src))
+ return (Overlappable (src, AnnPragma o' c' s l1 l2 t m))
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (Overlapping src)) = do
+ exact (Overlapping (src, AnnPragma o c s l1 l2 t m)) = do
o' <- markAnnOpen'' o src "{-# OVERLAPPING"
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1 l2 t m) cs) (Overlapping src))
+ return (Overlapping (src, AnnPragma o' c' s l1 l2 t m))
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (Overlaps src)) = do
+ exact (Overlaps (src, AnnPragma o c s l1 l2 t m)) = do
o' <- markAnnOpen'' o src "{-# OVERLAPS"
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1 l2 t m) cs) (Overlaps src))
+ return (Overlaps (src, AnnPragma o' c' s l1 l2 t m))
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (Incoherent src)) = do
+ exact (Incoherent (src, AnnPragma o c s l1 l2 t m)) = do
o' <- markAnnOpen'' o src "{-# INCOHERENT"
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1 l2 t m) cs) (Incoherent src))
+ return (Incoherent (src, AnnPragma o' c' s l1 l2 t m))
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (NonCanonical src)) = do
+ exact (NonCanonical (src, AnnPragma o c s l1 l2 t m)) = do
o' <- markAnnOpen'' o src "{-# INCOHERENT"
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1 l2 t m) cs) (Incoherent src))
+ return (Incoherent (src, AnnPragma o' c' s l1 l2 t m))
-- ---------------------------------------------------------------------
@@ -4407,13 +4407,14 @@ instance ExactPrint t => ExactPrint (HsModifierOf t GhcPs) where
-- ---------------------------------------------------------------------
-instance Typeable p => ExactPrint (LocatedP (CType (GhcPass p))) where
- getAnnotationEntry = entryFromLocatedA
- setAnnotationAnchor = setAnchorAn
+instance Typeable p => ExactPrint (CType (GhcPass p)) where
+ getAnnotationEntry _ = NoEntryVal
+ setAnnotationAnchor a _ _ _ = a
- exact (L (EpAnn l (AnnPragma o c s l1 l2 t m) cs) (CType ext mh ct)) = do
+ exact (CType ext mh ct) = do
let stp = cTypeSourceText ext
stct = cTypeOtherText ext
+ AnnPragma o c s l1 l2 t m = cTypeAnn ext
o' <- markAnnOpen'' o stp "{-# CTYPE"
l1' <- case mh of
Nothing -> return l1
@@ -4421,7 +4422,7 @@ instance Typeable p => ExactPrint (LocatedP (CType (GhcPass p))) where
printStringAtAA l1 (toSourceTextWithSuffix srcH "" "")
l2' <- printStringAtAA l2 (toSourceTextWithSuffix stct (unpackFS ct) "")
c' <- markEpToken c
- return (L (EpAnn l (AnnPragma o' c' s l1' l2' t m) cs) (CType ext mh ct))
+ return (CType (ext { cTypeAnn = AnnPragma o' c' s l1' l2' t m }) mh ct)
-- ---------------------------------------------------------------------
=====================================
utils/haddock/haddock-api/src/Haddock/Types.hs
=====================================
@@ -834,8 +834,8 @@ type instance Anno (FamilyResultSig DocNameI) = EpAnn NoEpAnns
type instance Anno (HsOuterTyVarBndrs Specificity DocNameI) = SrcSpanAnnA
type instance Anno (HsSigType DocNameI) = SrcSpanAnnA
type instance Anno (BooleanFormula DocNameI) = SrcSpanAnnBF
-type instance Anno (OverlapMode DocNameI) = EpAnn AnnPragma
-type instance Anno (CType DocNameI) = EpAnn AnnPragma
+type instance Anno (OverlapMode DocNameI) = SrcSpanAnnA
+type instance Anno (CType DocNameI) = SrcSpanAnnA
type instance Anno (Header DocNameI) = EpAnn AnnPragma
type instance Anno (HsModifierOf (LocatedA (HsType DocNameI)) DocNameI) = SrcSpanAnnA
type instance Anno (HsContextDetails DocNameI a) = SrcSpanAnnA
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7b5adaa3501d9a247d2f34a6796e35…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/7b5adaa3501d9a247d2f34a6796e35…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/udfm-placement] Use a placement sort for deterministic UniqDFM iteration
by Simon Jakobi (@sjakobi2) 02 Jul '26
by Simon Jakobi (@sjakobi2) 02 Jul '26
02 Jul '26
Simon Jakobi pushed to branch wip/sjakobi/udfm-placement at Glasgow Haskell Compiler / GHC
Commits:
1c645b9c by Simon Jakobi at 2026-07-02T21:26:00+02:00
Use a placement sort for deterministic UniqDFM iteration
eltsUDFM/udfmToList (and with them foldUDFM and UniqDFM's Foldable
instance) ordered elements with a list mergesort, allocating ~n*log n
cons cells per call. In the profile for the InstanceMatching1 perf test
this pipeline accounted for a large share of total allocations (#27459).
This commit instead uses a more efficient placement sort in most cases.
See Note [Sorting a UDFM].
Also add Note [Cost of deterministic iteration], prompted by #27459.
- - - - -
1 changed file:
- compiler/GHC/Types/Unique/DFM.hs
Changes:
=====================================
compiler/GHC/Types/Unique/DFM.hs
=====================================
@@ -14,6 +14,9 @@ See Note [Unique Determinism] in GHC.Types.Unique for explanation why @Unique@ o
is not deterministic.
-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+
{-# OPTIONS_GHC -Wall #-}
module GHC.Types.Unique.DFM (
@@ -79,6 +82,9 @@ import Data.Functor.Classes (Eq1 (..))
import Data.List (sortBy)
import Data.Function (on)
import GHC.Types.Unique.FM (UniqFM, nonDetUFMToList, ufmToIntMap, unsafeIntMapToUFM)
+import GHC.Data.SmallArray
+import GHC.Exts (State#)
+import GHC.ST (ST(..), runST)
import Unsafe.Coerce
import qualified GHC.Data.Word64Set as W
@@ -92,9 +98,10 @@ import qualified GHC.Data.Word64Set as W
-- order then `udfmToList` returns them in deterministic order.
--
-- There is an implementation cost: each element is given a serial number
--- as it is added, and `udfmToList` sorts its result by this serial
--- number. So you should only use `UniqDFM` if you need the deterministic
--- property.
+-- as it is added, and functions like `udfmToList` or `eltsUDFM` order their
+-- results by this serial number (see
+-- Note [Cost of deterministic iteration]). So you should only use `UniqDFM`
+-- if you need the deterministic property.
--
-- `foldUDFM` also preserves determinism.
--
@@ -112,13 +119,19 @@ import qualified GHC.Data.Word64Set as W
--
-- An alternative would be to have
--
--- data UniqDFM ele = UDFM (M.IntMap ele) [ele]
+-- data UniqDFM ele = UDFM (Word64Map ele) [ele]
--
-- where the list determines the order. This makes deletion tricky as we'd
-- only accumulate elements in that list, but makes merging easier as you
-- can just merge both structures independently.
-- Deletion can probably be done in amortized fashion when the size of the
-- list is twice the size of the set.
+--
+-- A representation like
+--
+-- data UniqDFM ele = UDFM (Word64Map ele) [Unique]
+--
+-- may also be worth considering. Compare Dhall.Map in the dhall package.
-- | A type of values tagged with insertion time
data TaggedVal val =
@@ -153,11 +166,15 @@ data UniqDFM key ele =
-- time. See Note [Overflow on plusUDFM]
deriving (Data, Functor)
--- | Deterministic, in O(n log n).
+-- | Deterministic.
+--
+-- See Note [Cost of deterministic iteration].
instance Foldable (UniqDFM key) where
foldr = foldUDFM
--- | Deterministic, in O(n log n).
+-- | Deterministic.
+--
+-- See Note [Cost of deterministic iteration].
instance Traversable (UniqDFM key) where
traverse f = fmap listToUDFM_Directly
. traverse (\(u,a) -> (u,) <$> f a)
@@ -310,13 +327,20 @@ elemUDFM :: Uniquable key => key -> UniqDFM key elt -> Bool
elemUDFM k (UDFM m _i) = M.member (getKey $ getUnique k) m
-- | Performs a deterministic fold over the UniqDFM.
--- It's O(n log n) while the corresponding function on `UniqFM` is O(n).
+--
+-- O(n) in the common case, with an O(n log n) fallback.
+--
+-- Don't use this to access the first element or to check for emptiness,
+-- as this already incurs most of the cost of returning the full list.
+-- See Note [Cost of deterministic iteration].
foldUDFM :: (elt -> a -> a) -> a -> UniqDFM key elt -> a
{-# INLINE foldUDFM #-}
-- This INLINE prevents a regression in !10568
foldUDFM k z m = foldr k z (eltsUDFM m)
--- | Like 'foldUDFM' but the function also receives a key
+-- | Like 'foldUDFM' but the function also receives a key.
+--
+-- See Note [Cost of deterministic iteration].
foldWithKeyUDFM :: (Unique -> elt -> a -> a) -> a -> UniqDFM key elt -> a
{-# INLINE foldWithKeyUDFM #-}
-- This INLINE was copied from foldUDFM
@@ -331,14 +355,88 @@ nonDetStrictFoldUDFM k z (UDFM m _i) = foldl' k' z m
where
k' acc (TaggedVal v _) = k v acc
+-- Note [Cost of deterministic iteration]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Deterministic iteration orders elements by insertion tag, and any such
+-- ordering must inspect every element's tag before it can emit the first
+-- element. So even the head of the result costs a full traversal of the map
+-- plus -- on the main path -- the allocation of an O(n)-sized array (see
+-- Note [Sorting a UDFM]). Laziness in the result list only avoids allocating
+-- for elements that are never demanded; it does not make the iteration
+-- incremental. #27459 shows this cost biting in consumers that demanded only
+-- the head.
+--
+-- So: to test for emptiness, use isNullUDFM rather than null on eltsUDFM;
+-- for order-oblivious queries, prefer short-circuiting anyUDFM/allUDFM; and
+-- if you don't need the deterministic order at all, use the nonDet functions.
+
+-- | Deterministic, in order of insertion.
+--
+-- See Note [Sorting a UDFM] and Note [Cost of deterministic iteration].
eltsUDFM :: UniqDFM key elt -> [elt]
-{-# INLINE eltsUDFM #-}
--- The INLINE makes it a good producer (from the map)
-eltsUDFM (UDFM m _i) = map taggedFst (sort_it m)
+eltsUDFM (UDFM m i)
+ | n <= 1 = map taggedFst (M.elems m)
+ | usePlacement n i = placementSort i (M.elems m)
+ | otherwise = map taggedFst (sort_it m)
+ where n = M.size m
sort_it :: M.Word64Map (TaggedVal elt) -> [TaggedVal elt]
sort_it m = sortBy (compare `on` taggedSnd) (M.elems m)
+
+-- Note [Sorting a UDFM]
+-- ~~~~~~~~~~~~~~~~~~~~~
+-- Deterministic iteration must order elements by insertion tag. Instead of a
+-- comparison sort -- the list mergesort behind sortBy allocates ~n*log n cons
+-- cells -- we exploit the invariant that in (UDFM m i) all tags are distinct
+-- Ints in [0, i): allocate an array of size i, write each element at
+-- @index = tag@, freeze, and read out in index order. That's O(i) work (which
+-- subsumes the O(n) fill, since distinct tags force n <= i), no comparisons,
+-- and the readout is lazy, so consumers that demand only a prefix pay almost
+-- nothing beyond the fill (but the fill itself is unavoidable; see
+-- Note [Cost of deterministic iteration]).
+--
+-- Holes: slots whose tag never occurs keep the initial sentinel, a TaggedVal
+-- with tag -1. Real tags are non-negative, so the readout skips on tag < 0;
+-- the sentinel's value field is never touched (it is unsafeCoerced ()).
+--
+-- This sorting method loses when i is much larger than n: i never shrinks
+-- (overwrites keep bumping it, delete/filter shrink n but not i). We compute
+-- n = M.size m (O(n), cheap next to either sort) and fall back to the
+-- mergesort when i > 4 * n. Maps built by plain insertion -- the common
+-- case -- have i == n. The guard also caps the fast path's O(i) at O(n).
+
+usePlacement :: Int -> Int -> Bool
+usePlacement n i = i <= 4 * n
+
+-- | Order a list of 'TaggedVal's by tag, by placing each at array index =
+-- its tag.
+--
+-- The tags must be distinct and in @[0, i)@.
+-- See Note [Sorting a UDFM].
+placementSort :: forall r. Int -> [TaggedVal r] -> [r]
+placementSort i tvs = runST (ST (\s0 ->
+ case newSmallArray i hole s0 of
+ (# s1, marr #) -> case fill marr tvs s1 of
+ s2 -> case unsafeFreezeSmallArray marr s2 of
+ (# s3, arr #) -> (# s3, readout arr 0 #)))
+ where
+ hole :: TaggedVal r
+ hole = TaggedVal (unsafeCoerce ()) (-1)
+
+ fill :: SmallMutableArray s (TaggedVal r) -> [TaggedVal r] -> State# s -> State# s
+ fill _ [] s = s
+ fill marr (tv : tvs') s =
+ case writeSmallArray marr (taggedSnd tv) tv s of
+ s' -> fill marr tvs' s'
+
+ readout :: SmallArray (TaggedVal r) -> Int -> [r]
+ readout arr j
+ | j >= i = []
+ | t < 0 = readout arr (j + 1)
+ | otherwise = v : readout arr (j + 1)
+ where TaggedVal v t = indexSmallArray arr j
+
filterUDFM :: (elt -> Bool) -> UniqDFM key elt -> UniqDFM key elt
filterUDFM p (UDFM m i) = UDFM (M.filter (\(TaggedVal v _) -> p v) m) i
@@ -356,11 +454,26 @@ udfmRestrictKeysSet (UDFM val_set i) set =
in UDFM (M.restrictKeys val_set key_set) i
-- | Converts `UniqDFM` to a list, with elements in deterministic order.
--- It's O(n log n) while the corresponding function on `UniqFM` is O(n).
+--
+-- O(n) in the common case, with an O(n log n) fallback.
+--
+-- Don't use this to access the first element or to check for emptiness,
+-- as this already incurs most of the cost of returning the full list.
+-- See Note [Cost of deterministic iteration].
udfmToList :: UniqDFM key elt -> [(Unique, elt)]
-udfmToList (UDFM m _i) =
- [ (mkUniqueGrimily k, taggedFst v)
- | (k, v) <- sortBy (compare `on` (taggedSnd . snd)) $ M.toList m ]
+udfmToList (UDFM m i)
+ | n <= 1 = [ (mkUniqueGrimily k, taggedFst v) | (k, v) <- M.toList m ]
+
+ -- Unlike eltsUDFM, this allocates a fresh TaggedVal + pair per element
+ -- before the sort. If it ever matters, a parallel Word64 array of
+ -- keys filled in the same pass would avoid the eager boxes.
+ | usePlacement n i = placementSort i
+ (M.foldrWithKey (\k tv rest ->
+ TaggedVal (mkUniqueGrimily k, taggedFst tv) (taggedSnd tv) : rest) [] m)
+ | otherwise =
+ [ (mkUniqueGrimily k, taggedFst v)
+ | (k, v) <- sortBy (compare `on` (taggedSnd . snd)) $ M.toList m ]
+ where n = M.size m
-- Determines whether two 'UniqDFM's contain the same keys.
equalKeysUDFM :: UniqDFM key a -> UniqDFM key b -> Bool
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1c645b9c8d5318d36dd37c23c4abb6a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1c645b9c8d5318d36dd37c23c4abb6a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/sjakobi/udfm-placement] Use a placement sort for deterministic UniqDFM iteration
by Simon Jakobi (@sjakobi2) 02 Jul '26
by Simon Jakobi (@sjakobi2) 02 Jul '26
02 Jul '26
Simon Jakobi pushed to branch wip/sjakobi/udfm-placement at Glasgow Haskell Compiler / GHC
Commits:
a06b74dc by Simon Jakobi at 2026-07-02T20:41:07+02:00
Use a placement sort for deterministic UniqDFM iteration
eltsUDFM/udfmToList (and with them foldUDFM and UniqDFM's Foldable
instance) ordered elements with a list mergesort, allocating ~n*log n
cons cells per call. In the profile of InstanceMatching1 this pipeline
accounted for a large share of total allocations (#27459).
This commit instead uses a placement sort in most cases. See
Note [Sorting a UDFM].
Also add Note [Cost of deterministic iteration], prompted by #27459.
- - - - -
1 changed file:
- compiler/GHC/Types/Unique/DFM.hs
Changes:
=====================================
compiler/GHC/Types/Unique/DFM.hs
=====================================
@@ -14,6 +14,9 @@ See Note [Unique Determinism] in GHC.Types.Unique for explanation why @Unique@ o
is not deterministic.
-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE UnboxedTuples #-}
+
{-# OPTIONS_GHC -Wall #-}
module GHC.Types.Unique.DFM (
@@ -79,6 +82,9 @@ import Data.Functor.Classes (Eq1 (..))
import Data.List (sortBy)
import Data.Function (on)
import GHC.Types.Unique.FM (UniqFM, nonDetUFMToList, ufmToIntMap, unsafeIntMapToUFM)
+import GHC.Data.SmallArray
+import GHC.Exts (State#)
+import GHC.ST (ST(..), runST)
import Unsafe.Coerce
import qualified GHC.Data.Word64Set as W
@@ -92,9 +98,10 @@ import qualified GHC.Data.Word64Set as W
-- order then `udfmToList` returns them in deterministic order.
--
-- There is an implementation cost: each element is given a serial number
--- as it is added, and `udfmToList` sorts its result by this serial
--- number. So you should only use `UniqDFM` if you need the deterministic
--- property.
+-- as it is added, and functions like `udfmToList` or `eltsUDFM` order their
+-- results by this serial number (see
+-- Note [Cost of deterministic iteration]). So you should only use `UniqDFM`
+-- if you need the deterministic property.
--
-- `foldUDFM` also preserves determinism.
--
@@ -112,13 +119,17 @@ import qualified GHC.Data.Word64Set as W
--
-- An alternative would be to have
--
--- data UniqDFM ele = UDFM (M.IntMap ele) [ele]
+-- data UniqDFM ele = UDFM (Word64Map ele) [ele]
--
-- where the list determines the order. This makes deletion tricky as we'd
-- only accumulate elements in that list, but makes merging easier as you
-- can just merge both structures independently.
-- Deletion can probably be done in amortized fashion when the size of the
-- list is twice the size of the set.
+--
+-- data UniqDFM ele = UDFM (Word64Map ele) [Unique]
+--
+-- may also be worth considering. Compare Dhall.Map in the dhall package.
-- | A type of values tagged with insertion time
data TaggedVal val =
@@ -153,11 +164,15 @@ data UniqDFM key ele =
-- time. See Note [Overflow on plusUDFM]
deriving (Data, Functor)
--- | Deterministic, in O(n log n).
+-- | Deterministic.
+--
+-- See Note [Cost of deterministic iteration].
instance Foldable (UniqDFM key) where
foldr = foldUDFM
--- | Deterministic, in O(n log n).
+-- | Deterministic.
+--
+-- See Note [Cost of deterministic iteration].
instance Traversable (UniqDFM key) where
traverse f = fmap listToUDFM_Directly
. traverse (\(u,a) -> (u,) <$> f a)
@@ -310,13 +325,20 @@ elemUDFM :: Uniquable key => key -> UniqDFM key elt -> Bool
elemUDFM k (UDFM m _i) = M.member (getKey $ getUnique k) m
-- | Performs a deterministic fold over the UniqDFM.
--- It's O(n log n) while the corresponding function on `UniqFM` is O(n).
+--
+-- O(n) in the common case, with an O(n log n) fallback.
+--
+-- Don't use this to access the first element or to check for emptiness,
+-- as this already incurs most of the cost of returning the full list.
+-- See Note [Cost of deterministic iteration].
foldUDFM :: (elt -> a -> a) -> a -> UniqDFM key elt -> a
{-# INLINE foldUDFM #-}
-- This INLINE prevents a regression in !10568
foldUDFM k z m = foldr k z (eltsUDFM m)
--- | Like 'foldUDFM' but the function also receives a key
+-- | Like 'foldUDFM' but the function also receives a key.
+--
+-- See Note [Cost of deterministic iteration].
foldWithKeyUDFM :: (Unique -> elt -> a -> a) -> a -> UniqDFM key elt -> a
{-# INLINE foldWithKeyUDFM #-}
-- This INLINE was copied from foldUDFM
@@ -331,14 +353,90 @@ nonDetStrictFoldUDFM k z (UDFM m _i) = foldl' k' z m
where
k' acc (TaggedVal v _) = k v acc
+-- Note [Cost of deterministic iteration]
+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+-- Deterministic iteration orders elements by insertion tag, and any such
+-- ordering must inspect every element's tag before it can emit the first
+-- element. So even the head of the result costs a full traversal of the map
+-- plus the allocation of an O(n)-sized array -- or, on the fallback path,
+-- O(n log n) cons cells (see Note [Sorting a UDFM]). Laziness in the result
+-- list only avoids allocating for elements that are never demanded; it does
+-- not make the iteration incremental. #27459 shows this cost biting in
+-- consumers that demanded only the head.
+--
+-- So: to test for emptiness, use isNullUDFM rather than null on eltsUDFM;
+-- for order-oblivious queries, prefer short-circuiting anyUDFM/allUDFM; and
+-- if you don't need the deterministic order at all, use the nonDet functions.
+
+-- | Deterministic, in order of insertion.
+--
+-- See Notes [Sorting a UDFM] and [Cost of deterministic iteration].
eltsUDFM :: UniqDFM key elt -> [elt]
{-# INLINE eltsUDFM #-}
-- The INLINE makes it a good producer (from the map)
-eltsUDFM (UDFM m _i) = map taggedFst (sort_it m)
+eltsUDFM (UDFM m i)
+ | n <= 1 = map taggedFst (M.elems m)
+ | usePlacement n i = placementSort i (M.elems m)
+ | otherwise = map taggedFst (sort_it m)
+ where n = M.size m
sort_it :: M.Word64Map (TaggedVal elt) -> [TaggedVal elt]
sort_it m = sortBy (compare `on` taggedSnd) (M.elems m)
+
+-- Note [Sorting a UDFM]
+-- ~~~~~~~~~~~~~~~~~~~~~
+-- Deterministic iteration must order elements by insertion tag. Instead of a
+-- comparison sort -- the list mergesort behind sortBy allocates ~n*log n cons
+-- cells -- we exploit the invariant that in (UDFM m i) all tags are distinct
+-- Ints in [0, i): allocate an array of size i, write each element at
+-- @index = tag@, freeze, and read out in index order. That's O(i) work (which
+-- subsumes the O(n) fill, since distinct tags force n <= i), no comparisons,
+-- and the readout is lazy, so consumers that demand only a prefix pay almost
+-- nothing beyond the fill (but the fill itself is unavoidable; see
+-- Note [Cost of deterministic iteration]).
+--
+-- Holes: slots whose tag never occurs keep the initial sentinel, a TaggedVal
+-- with tag -1. Real tags are non-negative, so the readout skips on tag < 0;
+-- the sentinel's value field is never touched (it is unsafeCoerced ()).
+--
+-- This sorting method loses when i is much larger than n: i never shrinks
+-- (overwrites keep bumping it, delete/filter shrink n but not i). We compute
+-- n = M.size m (O(n), cheap next to either sort) and fall back to the
+-- mergesort when i > 4 * n. Maps built by plain insertion -- the common
+-- case -- have i == n. The guard also caps the fast path's O(i) at O(n).
+
+usePlacement :: Int -> Int -> Bool
+usePlacement n i = i <= 4 * n
+
+-- | Order a list of 'TaggedVal's by tag, by placing each at array index =
+-- its tag.
+--
+-- The tags must be distinct and in @[0, i)@.
+-- See Note [Sorting a UDFM].
+placementSort :: forall r. Int -> [TaggedVal r] -> [r]
+placementSort i tvs = runST (ST (\s0 ->
+ case newSmallArray i hole s0 of
+ (# s1, marr #) -> case fill marr tvs s1 of
+ s2 -> case unsafeFreezeSmallArray marr s2 of
+ (# s3, arr #) -> (# s3, readout arr 0 #)))
+ where
+ hole :: TaggedVal r
+ hole = TaggedVal (unsafeCoerce ()) (-1)
+
+ fill :: SmallMutableArray s (TaggedVal r) -> [TaggedVal r] -> State# s -> State# s
+ fill _ [] s = s
+ fill marr (tv : tvs') s =
+ case writeSmallArray marr (taggedSnd tv) tv s of
+ s' -> fill marr tvs' s'
+
+ readout :: SmallArray (TaggedVal r) -> Int -> [r]
+ readout arr j
+ | j >= i = []
+ | t < 0 = readout arr (j + 1)
+ | otherwise = v : readout arr (j + 1)
+ where TaggedVal v t = indexSmallArray arr j
+
filterUDFM :: (elt -> Bool) -> UniqDFM key elt -> UniqDFM key elt
filterUDFM p (UDFM m i) = UDFM (M.filter (\(TaggedVal v _) -> p v) m) i
@@ -356,11 +454,25 @@ udfmRestrictKeysSet (UDFM val_set i) set =
in UDFM (M.restrictKeys val_set key_set) i
-- | Converts `UniqDFM` to a list, with elements in deterministic order.
--- It's O(n log n) while the corresponding function on `UniqFM` is O(n).
+--
+-- O(n) in the common case, with an O(n log n) fallback.
+--
+-- Don't use this to access the first element or to check for emptiness,
+-- as this already incurs most of the cost of returning the full list.
+-- See Note [Cost of deterministic iteration].
udfmToList :: UniqDFM key elt -> [(Unique, elt)]
-udfmToList (UDFM m _i) =
- [ (mkUniqueGrimily k, taggedFst v)
- | (k, v) <- sortBy (compare `on` (taggedSnd . snd)) $ M.toList m ]
+udfmToList (UDFM m i)
+ | n <= 1 = [ (mkUniqueGrimily k, taggedFst v) | (k, v) <- M.toList m ]
+ -- Unlike eltsUDFM, this allocates a fresh TaggedVal + pair per element
+ -- before the sort. If it ever matters, a parallel Word64 array of
+ -- keys filled in the same pass would avoid the eager boxes.
+ | usePlacement n i = placementSort i
+ (M.foldrWithKey (\k tv rest ->
+ TaggedVal (mkUniqueGrimily k, taggedFst tv) (taggedSnd tv) : rest) [] m)
+ | otherwise =
+ [ (mkUniqueGrimily k, taggedFst v)
+ | (k, v) <- sortBy (compare `on` (taggedSnd . snd)) $ M.toList m ]
+ where n = M.size m
-- Determines whether two 'UniqDFM's contain the same keys.
equalKeysUDFM :: UniqDFM key a -> UniqDFM key b -> Bool
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a06b74dc58af1433cb6d5a2c0952198…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a06b74dc58af1433cb6d5a2c0952198…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/jeltsch/ghc-9-14-building-base] Correct the path to `ghc`
by Wolfgang Jeltsch (@jeltsch) 02 Jul '26
by Wolfgang Jeltsch (@jeltsch) 02 Jul '26
02 Jul '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/ghc-9-14-building-base at Glasgow Haskell Compiler / GHC
Commits:
9532461e by Wolfgang Jeltsch at 2026-07-02T21:01:34+03:00
Correct the path to `ghc`
- - - - -
1 changed file:
- .gitlab-ci.yml
Changes:
=====================================
.gitlab-ci.yml
=====================================
@@ -1175,7 +1175,7 @@ base-build-with-released-ghcs:
make install
cd -
cd libraries/base
- cabal build --with-compiler ghc-${ghc_version}-installed/bin/ghc \
+ cabal build --with-compiler ../../ghc-${ghc_version}-installed/bin/ghc \
--allow-boot-library-installs \
-O0
cd -
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9532461e2cd966935981a7ecd479c75…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/9532461e2cd966935981a7ecd479c75…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Zubin pushed to branch wip/25924 at Glasgow Haskell Compiler / GHC
Commits:
e4e24735 by Zubin Duggal at 2026-07-02T21:58:04+05:30
accept failing tests
- - - - -
2 changed files:
- testsuite/tests/dmdanal/should_compile/T18982.stderr
- testsuite/tests/simplCore/should_compile/T26615.stderr
Changes:
=====================================
testsuite/tests/dmdanal/should_compile/T18982.stderr
=====================================
@@ -1,38 +1,26 @@
==================== Tidy Core ====================
-Result size of Tidy Core = {terms: 295, types: 206, coercions: 4, joins: 0/0}
-
--- RHS size: {terms: 8, types: 9, coercions: 1, joins: 0/0}
-T18982.$WExGADT :: forall e. (e ~ Int) => e %1 -> Int %1 -> ExGADT Int
-T18982.$WExGADT = \ (@e) (conrep :: e ~ Int) (conrep1 :: e) (conrep2 :: Int) -> T18982.ExGADT @Int @e @~(<Int>_N :: Int GHC.Internal.Prim.~# Int) conrep conrep1 conrep2
-
--- RHS size: {terms: 3, types: 2, coercions: 1, joins: 0/0}
-T18982.$WGADT :: Int %1 -> GADT Int
-T18982.$WGADT = \ (conrep :: Int) -> T18982.GADT @Int @~(<Int>_N :: Int GHC.Internal.Prim.~# Int) conrep
-
--- RHS size: {terms: 7, types: 6, coercions: 0, joins: 0/0}
-T18982.$WEx :: forall e a. e %1 -> a %1 -> Ex a
-T18982.$WEx = \ (@e) (@a) (conrep :: e) (conrep1 :: a) -> T18982.Ex @a @e conrep conrep1
+Result size of Tidy Core = {terms: 276, types: 179, coercions: 2, joins: 0/0}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$trModule4 :: GHC.Internal.Prim.Addr#
-T18982.$trModule4 = "main"#
+$trModule1 :: GHC.Internal.Prim.Addr#
+$trModule1 = "main"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$trModule3 :: GHC.Internal.Types.TrName
-T18982.$trModule3 = GHC.Internal.Types.TrNameS T18982.$trModule4
+$trModule2 :: GHC.Internal.Types.TrName
+$trModule2 = GHC.Internal.Types.TrNameS $trModule1
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$trModule2 :: GHC.Internal.Prim.Addr#
-T18982.$trModule2 = "T18982"#
+$trModule3 :: GHC.Internal.Prim.Addr#
+$trModule3 = "T18982"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$trModule1 :: GHC.Internal.Types.TrName
-T18982.$trModule1 = GHC.Internal.Types.TrNameS T18982.$trModule2
+$trModule4 :: GHC.Internal.Types.TrName
+$trModule4 = GHC.Internal.Types.TrNameS $trModule3
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
T18982.$trModule :: GHC.Internal.Types.Module
-T18982.$trModule = GHC.Internal.Types.Module T18982.$trModule3 T18982.$trModule1
+T18982.$trModule = GHC.Internal.Types.Module $trModule2 $trModule4
-- RHS size: {terms: 3, types: 1, coercions: 0, joins: 0/0}
$krep :: GHC.Internal.Types.KindRep
@@ -47,16 +35,16 @@ $krep2 :: GHC.Internal.Types.KindRep
$krep2 = GHC.Internal.Types.KindRepVar 0#
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcBox2 :: GHC.Internal.Prim.Addr#
-T18982.$tcBox2 = "Box"#
+$tcBox1 :: GHC.Internal.Prim.Addr#
+$tcBox1 = "Box"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcBox1 :: GHC.Internal.Types.TrName
-T18982.$tcBox1 = GHC.Internal.Types.TrNameS T18982.$tcBox2
+$tcBox2 :: GHC.Internal.Types.TrName
+$tcBox2 = GHC.Internal.Types.TrNameS $tcBox1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tcBox :: GHC.Internal.Types.TyCon
-T18982.$tcBox = GHC.Internal.Types.TyCon 16948648223906549518#Word64 2491460178135962649#Word64 T18982.$trModule T18982.$tcBox1 0# GHC.Internal.Types.krep$*Arr*
+T18982.$tcBox = GHC.Internal.Types.TyCon 16948648223906549518#Word64 2491460178135962649#Word64 T18982.$trModule $tcBox2 0# GHC.Internal.Types.krep$*Arr*
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
$krep3 :: [GHC.Internal.Types.KindRep]
@@ -67,140 +55,140 @@ $krep4 :: GHC.Internal.Types.KindRep
$krep4 = GHC.Internal.Types.KindRepTyConApp T18982.$tcBox $krep3
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'Box1 :: GHC.Internal.Types.KindRep
-T18982.$tc'Box1 = GHC.Internal.Types.KindRepFun $krep2 $krep4
+$krep5 :: GHC.Internal.Types.KindRep
+$krep5 = GHC.Internal.Types.KindRepFun $krep2 $krep4
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'Box3 :: GHC.Internal.Prim.Addr#
-T18982.$tc'Box3 = "'Box"#
+$tc'Box1 :: GHC.Internal.Prim.Addr#
+$tc'Box1 = "'Box"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'Box2 :: GHC.Internal.Types.TrName
-T18982.$tc'Box2 = GHC.Internal.Types.TrNameS T18982.$tc'Box3
+$tc'Box2 :: GHC.Internal.Types.TrName
+$tc'Box2 = GHC.Internal.Types.TrNameS $tc'Box1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tc'Box :: GHC.Internal.Types.TyCon
-T18982.$tc'Box = GHC.Internal.Types.TyCon 1412068769125067428#Word64 8727214667407894081#Word64 T18982.$trModule T18982.$tc'Box2 1# T18982.$tc'Box1
+T18982.$tc'Box = GHC.Internal.Types.TyCon 1412068769125067428#Word64 8727214667407894081#Word64 T18982.$trModule $tc'Box2 1# $krep5
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcEx2 :: GHC.Internal.Prim.Addr#
-T18982.$tcEx2 = "Ex"#
+$tcEx1 :: GHC.Internal.Prim.Addr#
+$tcEx1 = "Ex"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcEx1 :: GHC.Internal.Types.TrName
-T18982.$tcEx1 = GHC.Internal.Types.TrNameS T18982.$tcEx2
+$tcEx2 :: GHC.Internal.Types.TrName
+$tcEx2 = GHC.Internal.Types.TrNameS $tcEx1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tcEx :: GHC.Internal.Types.TyCon
-T18982.$tcEx = GHC.Internal.Types.TyCon 4376661818164435927#Word64 18005417598910668817#Word64 T18982.$trModule T18982.$tcEx1 0# GHC.Internal.Types.krep$*Arr*
+T18982.$tcEx = GHC.Internal.Types.TyCon 4376661818164435927#Word64 18005417598910668817#Word64 T18982.$trModule $tcEx2 0# GHC.Internal.Types.krep$*Arr*
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
-$krep5 :: [GHC.Internal.Types.KindRep]
-$krep5 = GHC.Internal.Types.: @GHC.Internal.Types.KindRep $krep1 (GHC.Internal.Types.[] @GHC.Internal.Types.KindRep)
+$krep6 :: [GHC.Internal.Types.KindRep]
+$krep6 = GHC.Internal.Types.: @GHC.Internal.Types.KindRep $krep1 (GHC.Internal.Types.[] @GHC.Internal.Types.KindRep)
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-$krep6 :: GHC.Internal.Types.KindRep
-$krep6 = GHC.Internal.Types.KindRepTyConApp T18982.$tcEx $krep5
+$krep7 :: GHC.Internal.Types.KindRep
+$krep7 = GHC.Internal.Types.KindRepTyConApp T18982.$tcEx $krep6
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-$krep7 :: GHC.Internal.Types.KindRep
-$krep7 = GHC.Internal.Types.KindRepFun $krep1 $krep6
+$krep8 :: GHC.Internal.Types.KindRep
+$krep8 = GHC.Internal.Types.KindRepFun $krep1 $krep7
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'Ex1 :: GHC.Internal.Types.KindRep
-T18982.$tc'Ex1 = GHC.Internal.Types.KindRepFun $krep2 $krep7
+$krep9 :: GHC.Internal.Types.KindRep
+$krep9 = GHC.Internal.Types.KindRepFun $krep2 $krep8
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'Ex3 :: GHC.Internal.Prim.Addr#
-T18982.$tc'Ex3 = "'Ex"#
+$tc'Ex1 :: GHC.Internal.Prim.Addr#
+$tc'Ex1 = "'Ex"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'Ex2 :: GHC.Internal.Types.TrName
-T18982.$tc'Ex2 = GHC.Internal.Types.TrNameS T18982.$tc'Ex3
+$tc'Ex2 :: GHC.Internal.Types.TrName
+$tc'Ex2 = GHC.Internal.Types.TrNameS $tc'Ex1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tc'Ex :: GHC.Internal.Types.TyCon
-T18982.$tc'Ex = GHC.Internal.Types.TyCon 14609381081172201359#Word64 3077219645053200509#Word64 T18982.$trModule T18982.$tc'Ex2 2# T18982.$tc'Ex1
+T18982.$tc'Ex = GHC.Internal.Types.TyCon 14609381081172201359#Word64 3077219645053200509#Word64 T18982.$trModule $tc'Ex2 2# $krep9
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcGADT2 :: GHC.Internal.Prim.Addr#
-T18982.$tcGADT2 = "GADT"#
+$tcGADT1 :: GHC.Internal.Prim.Addr#
+$tcGADT1 = "GADT"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcGADT1 :: GHC.Internal.Types.TrName
-T18982.$tcGADT1 = GHC.Internal.Types.TrNameS T18982.$tcGADT2
+$tcGADT2 :: GHC.Internal.Types.TrName
+$tcGADT2 = GHC.Internal.Types.TrNameS $tcGADT1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tcGADT :: GHC.Internal.Types.TyCon
-T18982.$tcGADT = GHC.Internal.Types.TyCon 9243924476135839950#Word64 5096619276488416461#Word64 T18982.$trModule T18982.$tcGADT1 0# GHC.Internal.Types.krep$*Arr*
+T18982.$tcGADT = GHC.Internal.Types.TyCon 9243924476135839950#Word64 5096619276488416461#Word64 T18982.$trModule $tcGADT2 0# GHC.Internal.Types.krep$*Arr*
-- RHS size: {terms: 3, types: 2, coercions: 0, joins: 0/0}
-$krep8 :: [GHC.Internal.Types.KindRep]
-$krep8 = GHC.Internal.Types.: @GHC.Internal.Types.KindRep $krep (GHC.Internal.Types.[] @GHC.Internal.Types.KindRep)
+$krep10 :: [GHC.Internal.Types.KindRep]
+$krep10 = GHC.Internal.Types.: @GHC.Internal.Types.KindRep $krep (GHC.Internal.Types.[] @GHC.Internal.Types.KindRep)
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-$krep9 :: GHC.Internal.Types.KindRep
-$krep9 = GHC.Internal.Types.KindRepTyConApp T18982.$tcGADT $krep8
+$krep11 :: GHC.Internal.Types.KindRep
+$krep11 = GHC.Internal.Types.KindRepTyConApp T18982.$tcGADT $krep10
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'GADT1 :: GHC.Internal.Types.KindRep
-T18982.$tc'GADT1 = GHC.Internal.Types.KindRepFun $krep $krep9
+$krep12 :: GHC.Internal.Types.KindRep
+$krep12 = GHC.Internal.Types.KindRepFun $krep $krep11
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'GADT3 :: GHC.Internal.Prim.Addr#
-T18982.$tc'GADT3 = "'GADT"#
+$tc'GADT1 :: GHC.Internal.Prim.Addr#
+$tc'GADT1 = "'GADT"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'GADT2 :: GHC.Internal.Types.TrName
-T18982.$tc'GADT2 = GHC.Internal.Types.TrNameS T18982.$tc'GADT3
+$tc'GADT2 :: GHC.Internal.Types.TrName
+$tc'GADT2 = GHC.Internal.Types.TrNameS $tc'GADT1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tc'GADT :: GHC.Internal.Types.TyCon
-T18982.$tc'GADT = GHC.Internal.Types.TyCon 2077850259354179864#Word64 16731205864486799217#Word64 T18982.$trModule T18982.$tc'GADT2 0# T18982.$tc'GADT1
+T18982.$tc'GADT = GHC.Internal.Types.TyCon 2077850259354179864#Word64 16731205864486799217#Word64 T18982.$trModule $tc'GADT2 0# $krep12
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcExGADT2 :: GHC.Internal.Prim.Addr#
-T18982.$tcExGADT2 = "ExGADT"#
+$tcExGADT1 :: GHC.Internal.Prim.Addr#
+$tcExGADT1 = "ExGADT"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tcExGADT1 :: GHC.Internal.Types.TrName
-T18982.$tcExGADT1 = GHC.Internal.Types.TrNameS T18982.$tcExGADT2
+$tcExGADT2 :: GHC.Internal.Types.TrName
+$tcExGADT2 = GHC.Internal.Types.TrNameS $tcExGADT1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tcExGADT :: GHC.Internal.Types.TyCon
-T18982.$tcExGADT = GHC.Internal.Types.TyCon 6470898418160489500#Word64 10361108917441214060#Word64 T18982.$trModule T18982.$tcExGADT1 0# GHC.Internal.Types.krep$*Arr*
+T18982.$tcExGADT = GHC.Internal.Types.TyCon 6470898418160489500#Word64 10361108917441214060#Word64 T18982.$trModule $tcExGADT2 0# GHC.Internal.Types.krep$*Arr*
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-$krep10 :: GHC.Internal.Types.KindRep
-$krep10 = GHC.Internal.Types.KindRepTyConApp T18982.$tcExGADT $krep8
+$krep13 :: GHC.Internal.Types.KindRep
+$krep13 = GHC.Internal.Types.KindRepTyConApp T18982.$tcExGADT $krep10
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-$krep11 :: GHC.Internal.Types.KindRep
-$krep11 = GHC.Internal.Types.KindRepFun $krep $krep10
+$krep14 :: GHC.Internal.Types.KindRep
+$krep14 = GHC.Internal.Types.KindRepFun $krep $krep13
-- RHS size: {terms: 3, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'ExGADT1 :: GHC.Internal.Types.KindRep
-T18982.$tc'ExGADT1 = GHC.Internal.Types.KindRepFun $krep2 $krep11
+$krep15 :: GHC.Internal.Types.KindRep
+$krep15 = GHC.Internal.Types.KindRepFun $krep2 $krep14
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'ExGADT3 :: GHC.Internal.Prim.Addr#
-T18982.$tc'ExGADT3 = "'ExGADT"#
+$tc'ExGADT1 :: GHC.Internal.Prim.Addr#
+$tc'ExGADT1 = "'ExGADT"#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
-T18982.$tc'ExGADT2 :: GHC.Internal.Types.TrName
-T18982.$tc'ExGADT2 = GHC.Internal.Types.TrNameS T18982.$tc'ExGADT3
+$tc'ExGADT2 :: GHC.Internal.Types.TrName
+$tc'ExGADT2 = GHC.Internal.Types.TrNameS $tc'ExGADT1
-- RHS size: {terms: 7, types: 0, coercions: 0, joins: 0/0}
T18982.$tc'ExGADT :: GHC.Internal.Types.TyCon
-T18982.$tc'ExGADT = GHC.Internal.Types.TyCon 8468257409157161049#Word64 5503123603717080600#Word64 T18982.$trModule T18982.$tc'ExGADT2 1# T18982.$tc'ExGADT1
+T18982.$tc'ExGADT = GHC.Internal.Types.TyCon 8468257409157161049#Word64 5503123603717080600#Word64 T18982.$trModule $tc'ExGADT2 1# $krep15
--- RHS size: {terms: 11, types: 10, coercions: 0, joins: 0/0}
-T18982.$wi :: forall a e. (a GHC.Internal.Prim.~# Int) => e -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int#
-T18982.$wi = \ (@a) (@e) (ww :: a GHC.Internal.Prim.~# Int) (ww1 :: e) (ww2 :: GHC.Internal.Prim.Int#) -> case ww1 of { __DEFAULT -> GHC.Internal.Prim.+# ww2 1# }
+-- RHS size: {terms: 12, types: 14, coercions: 0, joins: 0/0}
+T18982.$wi :: forall a e. (a GHC.Internal.Prim.~# Int, e ~ Int) => e -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int#
+T18982.$wi = \ (@a) (@e) (ww :: a GHC.Internal.Prim.~# Int) (ww1 :: e ~ Int) (ww2 :: e) (ww3 :: GHC.Internal.Prim.Int#) -> case ww2 of { __DEFAULT -> GHC.Internal.Prim.+# ww3 1# }
--- RHS size: {terms: 15, types: 22, coercions: 1, joins: 0/0}
+-- RHS size: {terms: 16, types: 22, coercions: 1, joins: 0/0}
i :: forall a. ExGADT a -> Int
-i = \ (@a) (ds :: ExGADT a) -> case ds of { ExGADT @e ww ww1 ww2 ww3 -> case ww3 of { GHC.Internal.Types.I# ww4 -> case T18982.$wi @a @e @~(ww :: a GHC.Internal.Prim.~# Int) ww2 ww4 of ww5 { __DEFAULT -> GHC.Internal.Types.I# ww5 } } }
+i = \ (@a) (ds :: ExGADT a) -> case ds of { ExGADT @e ww ww1 ww2 ww3 -> case ww3 of { GHC.Internal.Types.I# ww4 -> case T18982.$wi @a @e @~(ww :: a GHC.Internal.Prim.~# Int) ww1 ww2 ww4 of ww5 { __DEFAULT -> GHC.Internal.Types.I# ww5 } } }
-- RHS size: {terms: 6, types: 7, coercions: 0, joins: 0/0}
T18982.$wh :: forall a. (a GHC.Internal.Prim.~# Int) => GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int#
=====================================
testsuite/tests/simplCore/should_compile/T26615.stderr
=====================================
@@ -2,7 +2,7 @@
==================== Tidy Core ====================
Result size of Tidy Core
- = {terms: 1,209, types: 1,155, coercions: 18, joins: 17/29}
+ = {terms: 1,229, types: 1,163, coercions: 18, joins: 17/29}
-- RHS size: {terms: 6, types: 8, coercions: 0, joins: 0/0}
unArray :: forall a. Array a -> SmallArray# a
@@ -414,7 +414,7 @@ T26615a.$tc'BitmapIndexed
2#
$krep24
--- RHS size: {terms: 98, types: 109, coercions: 0, joins: 3/4}
+-- RHS size: {terms: 101, types: 113, coercions: 0, joins: 3/4}
T26615a.$wdisjointCollisions [InlPrag=INLINABLE[2]]
:: forall k a b.
Eq k =>
@@ -561,13 +561,14 @@ T26615a.$wdisjointCollisions
joinrec {
$wlookupInArrayCont_ [InlPrag=[2],
Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
- :: k -> SmallArray# (Leaf k b) -> Int# -> Int# -> Bool
- [LclId[JoinId(4)(Just [!])],
- Arity=4,
- Str=<1L><L><L><L>,
+ Dmd=SC(S,C(1,C(1,C(1,C(1,L)))))]
+ :: Eq k => k -> SmallArray# (Leaf k b) -> Int# -> Int# -> Bool
+ [LclId[JoinId(5)(Just [~, !])],
+ Arity=5,
+ Str=<A><1L><L><L><L>,
Unf=OtherCon []]
- $wlookupInArrayCont_ (k1 :: k)
+ $wlookupInArrayCont_ ($dEq1 [Occ=Dead] :: Eq k)
+ (k1 :: k)
(ww3 :: SmallArray# (Leaf k b))
(ww4 :: Int#)
(ww5 :: Int#)
@@ -578,7 +579,7 @@ T26615a.$wdisjointCollisions
{ (# ipv2 #) ->
case ipv2 of { L kx v ->
case == @k $dEq k2 kx of {
- False -> jump $wlookupInArrayCont_ k2 ww3 (+# ww4 1#) ww5;
+ False -> jump $wlookupInArrayCont_ $dEq k2 ww3 (+# ww4 1#) ww5;
True -> GHC.Internal.Types.False
}
}
@@ -586,7 +587,7 @@ T26615a.$wdisjointCollisions
1# -> jump $j
}
}; } in
- jump $wlookupInArrayCont_ kA ww2 0# lvl2
+ jump $wlookupInArrayCont_ $dEq kA ww2 0# lvl2
}
};
1# -> sc3
@@ -611,7 +612,7 @@ lvl1
= GHC.Internal.Control.Exception.Base.patError @LiftedRep @() lvl
Rec {
--- RHS size: {terms: 133, types: 126, coercions: 0, joins: 1/2}
+-- RHS size: {terms: 136, types: 130, coercions: 0, joins: 1/2}
T26615a.disjointSubtrees_$s$wdisjointSubtrees [InlPrag=INLINABLE[2],
Occ=LoopBreaker]
:: forall k a b.
@@ -641,13 +642,14 @@ T26615a.disjointSubtrees_$s$wdisjointSubtrees
joinrec {
$wlookupInArrayCont_ [InlPrag=[2],
Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
- :: k -> SmallArray# (Leaf k a) -> Int# -> Int# -> Bool
- [LclId[JoinId(4)(Just [!])],
- Arity=4,
- Str=<1L><L><L><L>,
+ Dmd=SC(S,C(1,C(1,C(1,C(1,L)))))]
+ :: Eq k => k -> SmallArray# (Leaf k a) -> Int# -> Int# -> Bool
+ [LclId[JoinId(5)(Just [~, !])],
+ Arity=5,
+ Str=<A><1L><L><L><L>,
Unf=OtherCon []]
- $wlookupInArrayCont_ (k1 :: k)
+ $wlookupInArrayCont_ ($dEq [Occ=Dead] :: Eq k)
+ (k1 :: k)
(ww :: SmallArray# (Leaf k a))
(ww1 :: Int#)
(ww2 :: Int#)
@@ -657,7 +659,7 @@ T26615a.disjointSubtrees_$s$wdisjointSubtrees
case indexSmallArray# @Lifted @(Leaf k a) ww ww1 of { (# ipv #) ->
case ipv of { L kx v ->
case == @k sc k2 kx of {
- False -> jump $wlookupInArrayCont_ k2 ww (+# ww1 1#) ww2;
+ False -> jump $wlookupInArrayCont_ sc k2 ww (+# ww1 1#) ww2;
True -> GHC.Internal.Types.False
}
}
@@ -666,7 +668,7 @@ T26615a.disjointSubtrees_$s$wdisjointSubtrees
}
}; } in
jump $wlookupInArrayCont_
- k0 sc3 0# (sizeofSmallArray# @Lifted @(Leaf k a) sc3)
+ sc k0 sc3 0# (sizeofSmallArray# @Lifted @(Leaf k a) sc3)
}
}
};
@@ -708,7 +710,7 @@ T26615a.disjointSubtrees_$s$wdisjointSubtrees
end Rec }
Rec {
--- RHS size: {terms: 705, types: 748, coercions: 18, joins: 13/23}
+-- RHS size: {terms: 719, types: 748, coercions: 18, joins: 13/23}
T26615a.$wdisjointSubtrees [InlPrag=INLINABLE[2], Occ=LoopBreaker]
:: forall k a b. Eq k => Int# -> HashMap k a -> HashMap k b -> Bool
[GblId[StrictWorker([~, ~, !])],
@@ -1065,23 +1067,23 @@ T26615a.$wdisjointSubtrees [InlPrag=INLINABLE[2], Occ=LoopBreaker]
@(*)
@(SmallArray# (HashMap k a)
-> SmallArray# (HashMap k b) -> Int#)
- @(GHC.Internal.Types.UnusedType 0 "a"
- -> GHC.Internal.Types.UnusedType 1 "b" -> Int#)
+ @(GHC.Internal.Types.UnusedType "a_0"
+ -> GHC.Internal.Types.UnusedType "b_1" -> Int#)
of
{ GHC.Internal.Unsafe.Coerce.UnsafeRefl v2 ->
case reallyUnsafePtrEquality#
@Lifted
@Lifted
- @(GHC.Internal.Types.UnusedType 0 "a")
- @(GHC.Internal.Types.UnusedType 1 "b")
+ @(GHC.Internal.Types.UnusedType "a_0")
+ @(GHC.Internal.Types.UnusedType "b_1")
(bx1
`cast` (SelCo:Fun(arg) (Sub (Sym v2))
:: SmallArray# (HashMap k a)
- ~R# GHC.Internal.Types.UnusedType 0 "a"))
+ ~R# GHC.Internal.Types.UnusedType "a_0"))
(bx3
`cast` (SelCo:Fun(arg) (SelCo:Fun(res) (Sub (Sym v2)))
:: SmallArray# (HashMap k b)
- ~R# GHC.Internal.Types.UnusedType 1 "b"))
+ ~R# GHC.Internal.Types.UnusedType "b_1"))
of {
__DEFAULT ->
joinrec {
@@ -1234,23 +1236,23 @@ T26615a.$wdisjointSubtrees [InlPrag=INLINABLE[2], Occ=LoopBreaker]
case GHC.Internal.Unsafe.Coerce.unsafeEqualityProof
@(*)
@(SmallArray# (HashMap k a) -> SmallArray# (HashMap k b) -> Int#)
- @(GHC.Internal.Types.UnusedType 0 "a"
- -> GHC.Internal.Types.UnusedType 1 "b" -> Int#)
+ @(GHC.Internal.Types.UnusedType "a_0"
+ -> GHC.Internal.Types.UnusedType "b_1" -> Int#)
of
{ GHC.Internal.Unsafe.Coerce.UnsafeRefl v2 ->
case reallyUnsafePtrEquality#
@Lifted
@Lifted
- @(GHC.Internal.Types.UnusedType 0 "a")
- @(GHC.Internal.Types.UnusedType 1 "b")
+ @(GHC.Internal.Types.UnusedType "a_0")
+ @(GHC.Internal.Types.UnusedType "b_1")
(bx
`cast` (SelCo:Fun(arg) (Sub (Sym v2))
:: SmallArray# (HashMap k a)
- ~R# GHC.Internal.Types.UnusedType 0 "a"))
+ ~R# GHC.Internal.Types.UnusedType "a_0"))
(bx1
`cast` (SelCo:Fun(arg) (SelCo:Fun(res) (Sub (Sym v2)))
:: SmallArray# (HashMap k b)
- ~R# GHC.Internal.Types.UnusedType 1 "b"))
+ ~R# GHC.Internal.Types.UnusedType "b_1"))
of {
__DEFAULT -> jump go (GHC.Internal.Types.I# 31#);
1# -> GHC.Internal.Types.False
@@ -1310,13 +1312,14 @@ T26615a.$wdisjointSubtrees
joinrec {
$wlookupInArrayCont_ [InlPrag=[2],
Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
- :: k -> SmallArray# (Leaf k a) -> Int# -> Int# -> Bool
- [LclId[JoinId(4)(Just [!])],
- Arity=4,
- Str=<1L><L><L><L>,
+ Dmd=SC(S,C(1,C(1,C(1,C(1,L)))))]
+ :: Eq k => k -> SmallArray# (Leaf k a) -> Int# -> Int# -> Bool
+ [LclId[JoinId(5)(Just [~, !])],
+ Arity=5,
+ Str=<A><1L><L><L><L>,
Unf=OtherCon []]
- $wlookupInArrayCont_ (k1 :: k)
+ $wlookupInArrayCont_ ($dEq1 [Occ=Dead] :: Eq k)
+ (k1 :: k)
(ww2 :: SmallArray# (Leaf k a))
(ww3 :: Int#)
(ww4 :: Int#)
@@ -1327,7 +1330,8 @@ T26615a.$wdisjointSubtrees
{ (# ipv #) ->
case ipv of { L kx v ->
case == @k $dEq k2 kx of {
- False -> jump $wlookupInArrayCont_ k2 ww2 (+# ww3 1#) ww4;
+ False ->
+ jump $wlookupInArrayCont_ $dEq k2 ww2 (+# ww3 1#) ww4;
True -> GHC.Internal.Types.False
}
}
@@ -1336,18 +1340,19 @@ T26615a.$wdisjointSubtrees
}
}; } in
jump $wlookupInArrayCont_
- ds4 bx2 0# (sizeofSmallArray# @Lifted @(Leaf k a) bx2)
+ $dEq ds4 bx2 0# (sizeofSmallArray# @Lifted @(Leaf k a) bx2)
} } in
joinrec {
$wlookupCont_ [InlPrag=[2],
Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
- :: Word# -> k -> Int# -> HashMap k a -> Bool
- [LclId[JoinId(4)(Just [~, !, ~, !])],
- Arity=4,
- Str=<L><1L><L><1L>,
+ Dmd=SC(S,C(1,C(1,C(1,C(1,L)))))]
+ :: Eq k => Word# -> k -> Int# -> HashMap k a -> Bool
+ [LclId[JoinId(5)(Just [~, ~, !, ~, !])],
+ Arity=5,
+ Str=<A><L><1L><L><1L>,
Unf=OtherCon []]
- $wlookupCont_ (ww1 :: Word#)
+ $wlookupCont_ ($dEq1 [Occ=Dead] :: Eq k)
+ (ww1 :: Word#)
(ds4 :: k)
(ww2 :: Int#)
(ds5 :: HashMap k a)
@@ -1371,7 +1376,7 @@ T26615a.$wdisjointSubtrees
(word2Int# (popCnt# (and# bx1 (minusWord# m 1##))))
of
{ (# ipv #) ->
- jump $wlookupCont_ ww1 ds6 (+# ww2 5#) ipv
+ jump $wlookupCont_ $dEq ww1 ds6 (+# ww2 5#) ipv
};
0## -> GHC.Internal.Types.True
};
@@ -1383,11 +1388,11 @@ T26615a.$wdisjointSubtrees
(word2Int# (and# (uncheckedShiftRL# ww1 ww2) 31##))
of
{ (# ipv #) ->
- jump $wlookupCont_ ww1 ds6 (+# ww2 5#) ipv
+ jump $wlookupCont_ $dEq ww1 ds6 (+# ww2 5#) ipv
}
}
}; } in
- jump $wlookupCont_ bx k0 ww ds
+ jump $wlookupCont_ $dEq bx k0 ww ds
}
};
Collision bx bx1 ->
@@ -1435,13 +1440,14 @@ T26615a.$wdisjointSubtrees
joinrec {
$wlookupInArrayCont_ [InlPrag=[2],
Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
- :: k -> SmallArray# (Leaf k b) -> Int# -> Int# -> Bool
- [LclId[JoinId(4)(Just [!])],
- Arity=4,
- Str=<1L><L><L><L>,
+ Dmd=SC(S,C(1,C(1,C(1,C(1,L)))))]
+ :: Eq k => k -> SmallArray# (Leaf k b) -> Int# -> Int# -> Bool
+ [LclId[JoinId(5)(Just [~, !])],
+ Arity=5,
+ Str=<A><1L><L><L><L>,
Unf=OtherCon []]
- $wlookupInArrayCont_ (k1 :: k)
+ $wlookupInArrayCont_ ($dEq1 [Occ=Dead] :: Eq k)
+ (k1 :: k)
(ww2 :: SmallArray# (Leaf k b))
(ww3 :: Int#)
(ww4 :: Int#)
@@ -1452,7 +1458,7 @@ T26615a.$wdisjointSubtrees
{ (# ipv #) ->
case ipv of { L kx v ->
case == @k $dEq k2 kx of {
- False -> jump $wlookupInArrayCont_ k2 ww2 (+# ww3 1#) ww4;
+ False -> jump $wlookupInArrayCont_ $dEq k2 ww2 (+# ww3 1#) ww4;
True -> GHC.Internal.Types.False
}
}
@@ -1461,18 +1467,19 @@ T26615a.$wdisjointSubtrees
}
}; } in
jump $wlookupInArrayCont_
- ds3 bx2 0# (sizeofSmallArray# @Lifted @(Leaf k b) bx2)
+ $dEq ds3 bx2 0# (sizeofSmallArray# @Lifted @(Leaf k b) bx2)
} } in
joinrec {
$wlookupCont_ [InlPrag=[2],
Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
- :: Word# -> k -> Int# -> HashMap k b -> Bool
- [LclId[JoinId(4)(Just [~, !, ~, !])],
- Arity=4,
- Str=<L><1L><L><1L>,
+ Dmd=SC(S,C(1,C(1,C(1,C(1,L)))))]
+ :: Eq k => Word# -> k -> Int# -> HashMap k b -> Bool
+ [LclId[JoinId(5)(Just [~, ~, !, ~, !])],
+ Arity=5,
+ Str=<A><L><1L><L><1L>,
Unf=OtherCon []]
- $wlookupCont_ (ww1 :: Word#)
+ $wlookupCont_ ($dEq1 [Occ=Dead] :: Eq k)
+ (ww1 :: Word#)
(ds3 :: k)
(ww2 :: Int#)
(ds4 :: HashMap k b)
@@ -1496,7 +1503,7 @@ T26615a.$wdisjointSubtrees
(word2Int# (popCnt# (and# bx1 (minusWord# m 1##))))
of
{ (# ipv #) ->
- jump $wlookupCont_ ww1 ds5 (+# ww2 5#) ipv
+ jump $wlookupCont_ $dEq ww1 ds5 (+# ww2 5#) ipv
};
0## -> GHC.Internal.Types.True
};
@@ -1508,11 +1515,11 @@ T26615a.$wdisjointSubtrees
(word2Int# (and# (uncheckedShiftRL# ww1 ww2) 31##))
of
{ (# ipv #) ->
- jump $wlookupCont_ ww1 ds5 (+# ww2 5#) ipv
+ jump $wlookupCont_ $dEq ww1 ds5 (+# ww2 5#) ipv
}
}
}; } in
- jump $wlookupCont_ bx k0 ww wild2
+ jump $wlookupCont_ $dEq bx k0 ww wild2
};
Leaf bx1 ds3 ->
case ds3 of { L kB ds4 ->
@@ -1570,23 +1577,23 @@ T26615a.$wdisjointSubtrees
case GHC.Internal.Unsafe.Coerce.unsafeEqualityProof
@(*)
@(SmallArray# (HashMap k a) -> SmallArray# (HashMap k b) -> Int#)
- @(GHC.Internal.Types.UnusedType 0 "a"
- -> GHC.Internal.Types.UnusedType 1 "b" -> Int#)
+ @(GHC.Internal.Types.UnusedType "a_0"
+ -> GHC.Internal.Types.UnusedType "b_1" -> Int#)
of
{ GHC.Internal.Unsafe.Coerce.UnsafeRefl v2 ->
case reallyUnsafePtrEquality#
@Lifted
@Lifted
- @(GHC.Internal.Types.UnusedType 0 "a")
- @(GHC.Internal.Types.UnusedType 1 "b")
+ @(GHC.Internal.Types.UnusedType "a_0")
+ @(GHC.Internal.Types.UnusedType "b_1")
(bx1
`cast` (SelCo:Fun(arg) (Sub (Sym v2))
:: SmallArray# (HashMap k a)
- ~R# GHC.Internal.Types.UnusedType 0 "a"))
+ ~R# GHC.Internal.Types.UnusedType "a_0"))
(bx3
`cast` (SelCo:Fun(arg) (SelCo:Fun(res) (Sub (Sym v2)))
:: SmallArray# (HashMap k b)
- ~R# GHC.Internal.Types.UnusedType 1 "b"))
+ ~R# GHC.Internal.Types.UnusedType "b_1"))
of {
__DEFAULT ->
let {
@@ -1715,23 +1722,23 @@ T26615a.$wdisjointSubtrees
case GHC.Internal.Unsafe.Coerce.unsafeEqualityProof
@(*)
@(SmallArray# (HashMap k a) -> SmallArray# (HashMap k b) -> Int#)
- @(GHC.Internal.Types.UnusedType 0 "a"
- -> GHC.Internal.Types.UnusedType 1 "b" -> Int#)
+ @(GHC.Internal.Types.UnusedType "a_0"
+ -> GHC.Internal.Types.UnusedType "b_1" -> Int#)
of
{ GHC.Internal.Unsafe.Coerce.UnsafeRefl v2 ->
case reallyUnsafePtrEquality#
@Lifted
@Lifted
- @(GHC.Internal.Types.UnusedType 0 "a")
- @(GHC.Internal.Types.UnusedType 1 "b")
+ @(GHC.Internal.Types.UnusedType "a_0")
+ @(GHC.Internal.Types.UnusedType "b_1")
(bx
`cast` (SelCo:Fun(arg) (Sub (Sym v2))
:: SmallArray# (HashMap k a)
- ~R# GHC.Internal.Types.UnusedType 0 "a"))
+ ~R# GHC.Internal.Types.UnusedType "a_0"))
(bx1
`cast` (SelCo:Fun(arg) (SelCo:Fun(res) (Sub (Sym v2)))
:: SmallArray# (HashMap k b)
- ~R# GHC.Internal.Types.UnusedType 1 "b"))
+ ~R# GHC.Internal.Types.UnusedType "b_1"))
of {
__DEFAULT ->
let {
@@ -1838,7 +1845,7 @@ disjointSubtrees
==================== Tidy Core ====================
Result size of Tidy Core
- = {terms: 614, types: 682, coercions: 18, joins: 8/14}
+ = {terms: 622, types: 674, coercions: 18, joins: 8/14}
-- RHS size: {terms: 1, types: 0, coercions: 0, joins: 0/0}
$trModule1 :: GHC.Internal.Prim.Addr#
@@ -1878,20 +1885,22 @@ lvl1
@GHC.Internal.Types.LiftedRep @() lvl
Rec {
--- RHS size: {terms: 37, types: 30, coercions: 0, joins: 0/0}
+-- RHS size: {terms: 39, types: 32, coercions: 0, joins: 0/0}
$wpoly_lookupInArrayCont_
:: forall a.
+ Eq String =>
String
-> GHC.Internal.Prim.SmallArray# (T26615a.Leaf String a)
-> GHC.Internal.Prim.Int#
-> GHC.Internal.Prim.Int#
-> Bool
-[GblId[StrictWorker([!])],
- Arity=4,
- Str=<1L><L><L><L>,
+[GblId[StrictWorker([~, !])],
+ Arity=5,
+ Str=<A><1L><L><L><L>,
Unf=OtherCon []]
$wpoly_lookupInArrayCont_
= \ (@a)
+ ($dEq2 [Occ=Dead] :: Eq String)
(k1 :: String)
(ww :: GHC.Internal.Prim.SmallArray# (T26615a.Leaf String a))
(ww1 :: GHC.Internal.Prim.Int#)
@@ -1907,7 +1916,12 @@ $wpoly_lookupInArrayCont_
case GHC.Internal.Base.eqString k2 kx of {
False ->
$wpoly_lookupInArrayCont_
- @a k2 ww (GHC.Internal.Prim.+# ww1 1#) ww2;
+ @a
+ GHC.Internal.Classes.$fEqList_$s$fEqList1
+ k2
+ ww
+ (GHC.Internal.Prim.+# ww1 1#)
+ ww2;
True -> GHC.Internal.Types.False
}
}
@@ -1918,17 +1932,19 @@ $wpoly_lookupInArrayCont_
end Rec }
Rec {
--- RHS size: {terms: 98, types: 73, coercions: 0, joins: 0/1}
+-- RHS size: {terms: 102, types: 75, coercions: 0, joins: 0/1}
$wpoly_lookupCont_
:: forall a.
+ Eq String =>
GHC.Internal.Prim.Word#
-> String -> GHC.Internal.Prim.Int# -> HashMap String a -> Bool
-[GblId[StrictWorker([~, !, ~, !])],
- Arity=4,
- Str=<L><1L><L><1L>,
+[GblId[StrictWorker([~, ~, !, ~, !])],
+ Arity=5,
+ Str=<A><L><1L><L><1L>,
Unf=OtherCon []]
$wpoly_lookupCont_
= \ (@a)
+ ($dEq1 [Occ=Dead] :: Eq String)
(ww :: GHC.Internal.Prim.Word#)
(ds5 :: String)
(ww1 :: GHC.Internal.Prim.Int#)
@@ -1953,6 +1969,7 @@ $wpoly_lookupCont_
1# ->
$wpoly_lookupInArrayCont_
@a
+ GHC.Internal.Classes.$fEqList_$s$fEqList1
ds9
bx2
0#
@@ -1979,7 +1996,13 @@ $wpoly_lookupCont_
(GHC.Internal.Prim.and# bx1 (GHC.Internal.Prim.minusWord# m 1##))))
of
{ (# ipv2 #) ->
- $wpoly_lookupCont_ @a ww ds9 (GHC.Internal.Prim.+# ww1 5#) ipv2
+ $wpoly_lookupCont_
+ @a
+ GHC.Internal.Classes.$fEqList_$s$fEqList1
+ ww
+ ds9
+ (GHC.Internal.Prim.+# ww1 5#)
+ ipv2
};
0## -> GHC.Internal.Types.True
};
@@ -1993,14 +2016,20 @@ $wpoly_lookupCont_
(GHC.Internal.Prim.uncheckedShiftRL# ww ww1) 31##))
of
{ (# ipv2 #) ->
- $wpoly_lookupCont_ @a ww ds9 (GHC.Internal.Prim.+# ww1 5#) ipv2
+ $wpoly_lookupCont_
+ @a
+ GHC.Internal.Classes.$fEqList_$s$fEqList1
+ ww
+ ds9
+ (GHC.Internal.Prim.+# ww1 5#)
+ ipv2
}
}
}
end Rec }
Rec {
--- RHS size: {terms: 448, types: 523, coercions: 18, joins: 8/13}
+-- RHS size: {terms: 450, types: 507, coercions: 18, joins: 8/13}
T26615.$s$wdisjointSubtrees [InlPrag=[~], Occ=LoopBreaker]
:: forall a b.
GHC.Internal.Prim.Int#
@@ -2021,7 +2050,8 @@ T26615.$s$wdisjointSubtrees
T26615a.Empty -> GHC.Internal.Types.True;
T26615a.Leaf bx ds2 ->
case ds2 of { T26615a.L kB ds3 ->
- $wpoly_lookupCont_ @a bx kB ww ds
+ $wpoly_lookupCont_
+ @a GHC.Internal.Classes.$fEqList_$s$fEqList1 bx kB ww ds
};
T26615a.Collision bx bx1 ->
T26615.$s$wdisjointSubtrees @b @a ww wild ds
@@ -2031,7 +2061,9 @@ T26615.$s$wdisjointSubtrees
T26615a.Leaf bx ds1 ->
case ds1 of { T26615a.L kA ds2 ->
case _b of wild2 {
- __DEFAULT -> $wpoly_lookupCont_ @b bx kA ww wild2;
+ __DEFAULT ->
+ $wpoly_lookupCont_
+ @b GHC.Internal.Classes.$fEqList_$s$fEqList1 bx kA ww wild2;
T26615a.Leaf bx1 ds3 ->
case ds3 of { T26615a.L kB ds4 ->
case GHC.Internal.Prim.neWord# bx bx1 of {
@@ -2085,9 +2117,9 @@ T26615.$s$wdisjointSubtrees
[LclId[JoinId(0)(Nothing)]]
$j = jump $s$wfoldr_ sc sc1 (GHC.Internal.Prim.+# sc2 1#) sc3 } in
joinrec {
- $wlookupInArrayCont_ [InlPrag=[2],
- Occ=LoopBreaker,
- Dmd=SC(S,C(1,C(1,C(1,L))))]
+ $w$slookupInArrayCont_ [InlPrag=[2],
+ Occ=LoopBreaker,
+ Dmd=SC(S,C(1,C(1,C(1,L))))]
:: String
-> GHC.Internal.Prim.SmallArray# (T26615a.Leaf String b)
-> GHC.Internal.Prim.Int#
@@ -2097,12 +2129,12 @@ T26615.$s$wdisjointSubtrees
Arity=4,
Str=<1L><L><L><L>,
Unf=OtherCon []]
- $wlookupInArrayCont_ (k1 :: String)
- (ww1
- :: GHC.Internal.Prim.SmallArray#
- (T26615a.Leaf String b))
- (ww2 :: GHC.Internal.Prim.Int#)
- (ww3 :: GHC.Internal.Prim.Int#)
+ $w$slookupInArrayCont_ (k1 :: String)
+ (ww1
+ :: GHC.Internal.Prim.SmallArray#
+ (T26615a.Leaf String b))
+ (ww2 :: GHC.Internal.Prim.Int#)
+ (ww3 :: GHC.Internal.Prim.Int#)
= case k1 of k2 { __DEFAULT ->
case GHC.Internal.Prim.>=# ww2 ww3 of {
__DEFAULT ->
@@ -2116,7 +2148,7 @@ T26615.$s$wdisjointSubtrees
case ipv5 of { T26615a.L kx v ->
case GHC.Internal.Base.eqString k2 kx of {
False ->
- jump $wlookupInArrayCont_
+ jump $w$slookupInArrayCont_
k2 ww1 (GHC.Internal.Prim.+# ww2 1#) ww3;
True -> GHC.Internal.Types.False
}
@@ -2125,7 +2157,7 @@ T26615.$s$wdisjointSubtrees
1# -> jump $j
}
}; } in
- jump $wlookupInArrayCont_ kA bx3 0# lvl2
+ jump $w$slookupInArrayCont_ kA bx3 0# lvl2
}
};
1# -> sc3
@@ -2187,23 +2219,23 @@ T26615.$s$wdisjointSubtrees
@(GHC.Internal.Prim.SmallArray# (HashMap String a)
-> GHC.Internal.Prim.SmallArray# (HashMap String b)
-> GHC.Internal.Prim.Int#)
- @(GHC.Internal.Types.UnusedType 0 "a"
- -> GHC.Internal.Types.UnusedType 1 "b" -> GHC.Internal.Prim.Int#)
+ @(GHC.Internal.Types.UnusedType "a_0"
+ -> GHC.Internal.Types.UnusedType "b_1" -> GHC.Internal.Prim.Int#)
of
{ GHC.Internal.Unsafe.Coerce.UnsafeRefl v2 ->
case GHC.Internal.Prim.reallyUnsafePtrEquality#
@GHC.Internal.Types.Lifted
@GHC.Internal.Types.Lifted
- @(GHC.Internal.Types.UnusedType 0 "a")
- @(GHC.Internal.Types.UnusedType 1 "b")
+ @(GHC.Internal.Types.UnusedType "a_0")
+ @(GHC.Internal.Types.UnusedType "b_1")
(bx1
`cast` (SelCo:Fun(arg) (Sub (Sym v2))
:: GHC.Internal.Prim.SmallArray# (HashMap String a)
- ~R# GHC.Internal.Types.UnusedType 0 "a"))
+ ~R# GHC.Internal.Types.UnusedType "a_0"))
(bx3
`cast` (SelCo:Fun(arg) (SelCo:Fun(res) (Sub (Sym v2)))
:: GHC.Internal.Prim.SmallArray# (HashMap String b)
- ~R# GHC.Internal.Types.UnusedType 1 "b"))
+ ~R# GHC.Internal.Types.UnusedType "b_1"))
of {
__DEFAULT ->
joinrec {
@@ -2365,23 +2397,23 @@ T26615.$s$wdisjointSubtrees
@(GHC.Internal.Prim.SmallArray# (HashMap String a)
-> GHC.Internal.Prim.SmallArray# (HashMap String b)
-> GHC.Internal.Prim.Int#)
- @(GHC.Internal.Types.UnusedType 0 "a"
- -> GHC.Internal.Types.UnusedType 1 "b" -> GHC.Internal.Prim.Int#)
+ @(GHC.Internal.Types.UnusedType "a_0"
+ -> GHC.Internal.Types.UnusedType "b_1" -> GHC.Internal.Prim.Int#)
of
{ GHC.Internal.Unsafe.Coerce.UnsafeRefl v2 ->
case GHC.Internal.Prim.reallyUnsafePtrEquality#
@GHC.Internal.Types.Lifted
@GHC.Internal.Types.Lifted
- @(GHC.Internal.Types.UnusedType 0 "a")
- @(GHC.Internal.Types.UnusedType 1 "b")
+ @(GHC.Internal.Types.UnusedType "a_0")
+ @(GHC.Internal.Types.UnusedType "b_1")
(bx
`cast` (SelCo:Fun(arg) (Sub (Sym v2))
:: GHC.Internal.Prim.SmallArray# (HashMap String a)
- ~R# GHC.Internal.Types.UnusedType 0 "a"))
+ ~R# GHC.Internal.Types.UnusedType "a_0"))
(bx1
`cast` (SelCo:Fun(arg) (SelCo:Fun(res) (Sub (Sym v2)))
:: GHC.Internal.Prim.SmallArray# (HashMap String b)
- ~R# GHC.Internal.Types.UnusedType 1 "b"))
+ ~R# GHC.Internal.Types.UnusedType "b_1"))
of {
__DEFAULT ->
joinrec {
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e4e24735545aa600febf194aac86757…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/e4e24735545aa600febf194aac86757…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/hadrian-target] hadrian: binary-dist-dir should not be the default target
by Zubin (@wz1000) 02 Jul '26
by Zubin (@wz1000) 02 Jul '26
02 Jul '26
Zubin pushed to branch wip/hadrian-target at Glasgow Haskell Compiler / GHC
Commits:
0e020352 by Zubin Duggal at 2026-07-02T21:53:46+05:30
hadrian: binary-dist-dir should not be the default target
Revert behaviour to pre 23c9b6c392f52ec9d7a8618b204ff6b885f5fba2
In 23c9b6c392f52ec9d7a8618b204ff6b885f5fba2, we applied the following behaviour change:
```
hadrian: Build stage 2 cross compilers
...
* hadrian: Make binary-dist-dir the default build target. This allows us
to have the logic in one place about which libraries/stages to build
with cross compilers. Fixes #24192
```
This is a major regression to development experience, a plain hadrian/build
--freeze1 now takes ages because we rebuild all docs (which need to go in the
binary dist dir).
`binary-dist-dir` is the wrong default target for regular GHC development work
Fixes #27445
- - - - -
2 changed files:
- hadrian/src/Rules.hs
- hadrian/src/Rules/BinaryDist.hs
Changes:
=====================================
hadrian/src/Rules.hs
=====================================
@@ -10,6 +10,7 @@ import qualified Hadrian.Oracles.Path
import qualified Hadrian.Oracles.TextFile
import qualified Hadrian.Haskell.Hash
+import BindistConfig
import Expression
import qualified Oracles.Flavour
import qualified Oracles.ModuleFiles
@@ -32,17 +33,49 @@ import Settings.Program (programContext)
import Target
import UserSettings
--- | This rule defines what the default build configuration is when no targets
--- are selected.
+-- | This rule calls 'need' on all top-level build targets that Hadrian builds
+-- by default, respecting the 'finalStage' flag.
topLevelTargets :: Rules ()
topLevelTargets = action $ do
- let targets = ["binary-dist-dir"]
+ verbosity <- getVerbosity
+ forM_ [ Stage1, Stage2, Stage3] $ \stage -> do
+ when (verbosity >= Verbose) $ do
+ (libraries, programs) <- partition isLibrary <$> stagePackages stage
+ libNames <- mapM (name stage) libraries
+ pgmNames <- mapM (name stage) programs
+ let stageHeader t ps =
+ "| Building " ++ show stage ++ " "
+ ++ t ++ ": " ++ intercalate ", " ps
+ putInfo . unlines $
+ [ stageHeader "libraries" libNames
+ , stageHeader "programs" pgmNames ]
+ let buildStages = [ s | s <- allStages, s < finalStage ]
+ targets <- concatForM buildStages $ \stage -> do
+ packages <- stagePackages stage
+ mapM (path stage) packages
+
+ -- For cross compilers, also build the target (stage 2) libraries.
+ cfg <- implicitBindistConfig
+ lib_targets <- if executable_stage cfg < finalStage
+ then map snd . fst <$> Rules.BinaryDist.bindistPackageTargets cfg
+ else return []
-- Why we need wrappers: https://gitlab.haskell.org/ghc/ghc/issues/16534.
root <- buildRoot
let wrappers = [ root -/- ("ghc-" ++ stageString s) | s <- [Stage1, Stage2, Stage3]
, s < finalStage ]
- need (targets ++ wrappers)
+ need (targets ++ lib_targets ++ wrappers)
+ where
+ -- either the package database config file for libraries or
+ -- the programPath for programs. However this still does
+ -- not support multiple targets, where a cabal package has
+ -- a library /and/ a program.
+ path :: Stage -> Package -> Action FilePath
+ path stage pkg | isLibrary pkg = pkgConfFile (vanillaContext stage pkg)
+ | otherwise = programPath =<< programContext stage pkg
+ name :: Stage -> Package -> Action String
+ name stage pkg | isLibrary pkg = return (pkgName pkg)
+ | otherwise = programName (vanillaContext stage pkg)
-- | Return the list of targets associated with a given 'Stage' and 'Package'.
packageTargets :: Stage -> Package -> Action [FilePath]
=====================================
hadrian/src/Rules/BinaryDist.hs
=====================================
@@ -124,11 +124,8 @@ installTo relocatable prefix = do
runBuilderWithCmdOptions env (Make bindistFilesDir) ["install"] [] []
-buildBinDistDir :: FilePath -> BindistConfig -> Action ()
-buildBinDistDir root conf@BindistConfig{..} = do
-
- verbosity <- getVerbosity
- -- We 'need' all binaries and libraries
+bindistPackageTargets :: BindistConfig -> Action ([(Package, FilePath)], [(Package, FilePath)])
+bindistPackageTargets conf@BindistConfig{..} = do
lib_pkgs <- stagePackages library_stage
(lib_targets, _) <- partitionEithers <$> mapM (pkgTarget conf) lib_pkgs
@@ -137,6 +134,14 @@ buildBinDistDir root conf@BindistConfig{..} = do
let excluded_packages = [ genapply ]
bin_pkgs = filter (`notElem` excluded_packages) bin_pkgs_all
(_, bin_targets) <- partitionEithers <$> mapM (pkgTarget conf) bin_pkgs
+ return (lib_targets, bin_targets)
+
+buildBinDistDir :: FilePath -> BindistConfig -> Action ()
+buildBinDistDir root conf@BindistConfig{..} = do
+
+ verbosity <- getVerbosity
+ -- We 'need' all binaries and libraries
+ (lib_targets, bin_targets) <- bindistPackageTargets conf
when (verbosity >= Verbose) $ do
let libNames = map (pkgName . fst) lib_targets
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0e0203528dfbad75f2d6ae79404a84a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/0e0203528dfbad75f2d6ae79404a84a…
You're receiving this email because of your account on gitlab.haskell.org.
1
0