
[Git][ghc/ghc][wip/T25943] rts/linker: Don't fail due to RTLD_NOW
by Ben Gamari (@bgamari) 02 May '25
by Ben Gamari (@bgamari) 02 May '25
02 May '25
Ben Gamari pushed to branch wip/T25943 at Glasgow Haskell Compiler / GHC
Commits:
6d92d6b6 by Ben Gamari at 2025-05-02T11:14:35-04:00
rts/linker: Don't fail due to RTLD_NOW
In !12264 we started using the NativeObj machinery introduced some time
ago for loading of shared objects. One of the side-effects of this
change is shared objects are now loaded eagerly (i.e. with `RTLD_NOW`).
This is needed by NativeObj to ensure full visibility of the mappings of
the loaded object, which is in turn needed for safe shared object
unloading.
Unfortunately, this change subtly regressed, causing compilation
failures in some programs. Specifically, shared objects which refer to
undefined symbols (e.g. which may be usually provided by either the
executable image or libraries loaded via `dlopen`) will fail to load
with eager binding. This is problematic as GHC loads all package
dependencies while, e.g., evaluating TemplateHaskell splices. This
results in compilation failures in programs depending upon (but not
using at compile-time) packages with undefined symbol references.
To mitigate this NativeObj now first attempts to load an object via
eager binding, reverting to lazy binding (and disabling unloading) on
failure.
See Note [Don't fail due to RTLD_NOW].
Fixes #25943.
- - - - -
1 changed file:
- rts/linker/LoadNativeObjPosix.c
Changes:
=====================================
rts/linker/LoadNativeObjPosix.c
=====================================
@@ -88,6 +88,26 @@ void freeNativeCode_POSIX (ObjectCode *nc) {
}
}
+/*
+ * Note [Don't fail due to RTLD_NOW]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * If possible we want to load dynamic objects immediately (e.g. using RTLD_NOW)
+ * so that we can query their mappings and therefore be able to safely unload
+ * them. However, there are some cases where an object cannot be
+ * successfully eagerly loaded yet execution can nevertheless
+ * succeed with lazy binding. One such instance was found in #25943, where
+ * a library referenced undefined symbols. While this pattern is quite dodgy
+ * (really, these symbol references should be weakly bound in the library),
+ * previous GHC versions accepted such programs. Moreover, it is important that
+ * we are able to load such libraries since GHC insists on loading all package
+ * dependencies when, e.g., evaluating TemplateHaskell splices.
+ *
+ * To ensure that we don't fail to load such programs, we first attempt
+ * loading with RTLD_NOW and, if this fails, attempt to load again
+ * with lazy binding (taking care to mark the object as not unloadable in
+ * this case).
+ */
+
void * loadNativeObj_POSIX (pathchar *path, char **errmsg)
{
ObjectCode* nc;
@@ -99,7 +119,6 @@ void * loadNativeObj_POSIX (pathchar *path, char **errmsg)
retval = NULL;
-
/* If we load the same object multiple times, just return the
* already-loaded handle. Note that this is broken if unloadNativeObj
* is used, as we don’t do any reference counting; see #24345.
@@ -116,6 +135,23 @@ void * loadNativeObj_POSIX (pathchar *path, char **errmsg)
nc = mkOc(DYNAMIC_OBJECT, path, NULL, 0, false, NULL, 0);
+ // If we HAVE_DLINFO, we use RTLD_NOW rather than RTLD_LAZY because we want
+ // to learn eagerly about all external functions. Otherwise, there is no
+ // additional advantage to being eager, so it is better to be lazy and only
+ // bind functions when needed for better performance.
+ //
+ // Moreover, it is possible that loading will fail (e.g. if the library
+ // being loaded depends upon symbols from a library which is not available);
+ // in this case we will retry loading with load_now=false. See
+ // Note [Don't fail due to RTLD_NOW]..
+ bool load_now;
+#if defined(HAVE_DLINFO)
+ load_now = true;
+#else
+ load_now = false;
+#endif
+
+try_again:
foreignExportsLoadingObject(nc);
// When dlopen() loads a profiled dynamic library, it calls the ctors which
@@ -129,17 +165,7 @@ void * loadNativeObj_POSIX (pathchar *path, char **errmsg)
ACQUIRE_LOCK(&ccs_mutex);
#endif
- // If we HAVE_DLINFO, we use RTLD_NOW rather than RTLD_LAZY because we want
- // to learn eagerly about all external functions. Otherwise, there is no
- // additional advantage to being eager, so it is better to be lazy and only bind
- // functions when needed for better performance.
- int dlopen_mode;
-#if defined(HAVE_DLINFO)
- dlopen_mode = RTLD_NOW;
-#else
- dlopen_mode = RTLD_LAZY;
-#endif
-
+ const int dlopen_mode = load_now ? RTLD_NOW : RTLD_LAZY;
hdl = dlopen(path, dlopen_mode|RTLD_LOCAL); /* see Note [RTLD_LOCAL] */
nc->dlopen_handle = hdl;
nc->status = OBJECT_READY;
@@ -151,31 +177,42 @@ void * loadNativeObj_POSIX (pathchar *path, char **errmsg)
foreignExportsFinishedLoadingObject();
if (hdl == NULL) {
- /* dlopen failed; save the message in errmsg */
- copyErrmsg(errmsg, dlerror());
- goto dlopen_fail;
+ if (load_now) {
+ // See Note [Don't fail due to RTLD_NOW]
+ load_now = false;
+ goto try_again;
+ } else {
+ /* dlopen failed; save the message in errmsg */
+ copyErrmsg(errmsg, dlerror());
+ goto dlopen_fail;
+ }
}
#if defined(HAVE_DLINFO)
- struct link_map *map;
- if (dlinfo(hdl, RTLD_DI_LINKMAP, &map) == -1) {
- /* dlinfo failed; save the message in errmsg */
- copyErrmsg(errmsg, dlerror());
- goto dlinfo_fail;
- }
+ if (load_now) {
+ struct link_map *map;
+ if (dlinfo(hdl, RTLD_DI_LINKMAP, &map) == -1) {
+ /* dlinfo failed; save the message in errmsg */
+ copyErrmsg(errmsg, dlerror());
+ goto dlinfo_fail;
+ }
- hdl = NULL; // pass handle ownership to nc
+ hdl = NULL; // pass handle ownership to nc
- struct piterate_cb_info piterate_info = {
- .nc = nc,
- .l_addr = (void *) map->l_addr
- };
- dl_iterate_phdr(loadNativeObjCb_, &piterate_info);
- if (!nc->nc_ranges) {
- copyErrmsg(errmsg, "dl_iterate_phdr failed to find obj");
- goto dl_iterate_phdr_fail;
+ struct piterate_cb_info piterate_info = {
+ .nc = nc,
+ .l_addr = (void *) map->l_addr
+ };
+ dl_iterate_phdr(loadNativeObjCb_, &piterate_info);
+ if (!nc->nc_ranges) {
+ copyErrmsg(errmsg, "dl_iterate_phdr failed to find obj");
+ goto dl_iterate_phdr_fail;
+ }
+ nc->unloadable = true;
+ } else {
+ nc->nc_ranges = NULL;
+ nc->unloadable = false;
}
- nc->unloadable = true;
#else
nc->nc_ranges = NULL;
nc->unloadable = false;
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6d92d6b60442c5a440a8dcfb3b4b8e9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6d92d6b60442c5a440a8dcfb3b4b8e9…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/romes/more-debugger] 31 commits: driver: Use ModuleGraph for oneshot and --make mode
by Rodrigo Mesquita (@alt-romes) 02 May '25
by Rodrigo Mesquita (@alt-romes) 02 May '25
02 May '25
Rodrigo Mesquita pushed to branch wip/romes/more-debugger at Glasgow Haskell Compiler / GHC
Commits:
d47bf776 by Matthew Pickering at 2025-04-14T16:44:41+01:00
driver: Use ModuleGraph for oneshot and --make mode
This patch uses the `hsc_mod_graph` field for both oneshot and --make
mode. Therefore, if part of the compiler requires usage of the module
graph, you do so in a uniform way for the two different modes.
The `ModuleGraph` describes the relationship between the modules in the
home package and units in external packages. The `ModuleGraph` can be
queried when information about the transitive closure of a package is
needed. For example, the primary use of the ModuleGraph from within the
compiler is in the loader, which needs to know the transitive closure of
a module so it can load all the relevant objects for evaluation.
In --make mode, downsweep computes the ModuleGraph before any
compilation starts.
In oneshot mode, a thunk is created at the start of compilation, which
when forced will compute the module graph beneath the current module.
The thunk is only forced at the moment when the user uses Template
Haskell.
Finally, there are some situations where we need to discover what
dependencies to load but haven't loaded a module graph at all. In this
case, there is a fallback which computes the transitive closure on the
fly and doesn't cache the result. Presumably if you are going to call
getLinkDeps a lot, you would compute the right ModuleGraph before you
started.
Importantly, this removes the ExternalModuleGraph abstraction. This was quite
awkward to work with since it stored information about the home package
inside the EPS.
This patch will also be very useful when implementing explicit level
imports, which requires more significant use of the module graph in
order to determine which level instances are available at.
Towards #25795
-------------------------
Metric Decrease:
MultiLayerModulesTH_Make
MultiLayerModulesTH_OneShot
-------------------------
- - - - -
395e0ad1 by sheaf at 2025-04-16T12:33:26-04:00
base: remove .Internal modules (e.g. GHC.TypeLits)
This commit removes the following internal modules from base,
as per CLC proposal 217:
- GHC.TypeNats.Internal
- GHC.TypeLits.Internal
- GHC.ExecutionStack.Internal
Fixes #25007
- - - - -
e0f3ff11 by Patrick at 2025-04-17T04:31:12-04:00
Refactor Handling of Multiple Default Declarations
Fixes: #25912, #25914, #25934
Previously, GHC discarded all loaded defaults (tcg_default) when local
defaults were encountered during typechecking. According to the
exportable-named-default proposal (sections 2.4.2 and 2.4.3), local
defaults should be merged into tcg_default, retaining any defaults
already present while overriding where necessary.
Key Changes:
* Introduce DefaultProvenance to track the origin of default declarations
(local, imported, or built-in), replacing the original cd_module
in ClassDefaults with cd_provenance :: DefaultProvenance.
* Rename tcDefaults to tcDefaultDecls, limiting its responsibility to only
converting renamed class defaults into ClassDefaults.
* Add extendDefaultEnvWithLocalDefaults to merge local defaults into the
environment, with proper duplication checks:
- Duplicate local defaults for a class trigger an error.
- Local defaults override imported or built-in defaults.
* Update and add related notes: Note [Builtin class defaults],
Note [DefaultProvenance].
* Add regression tests: T25912, T25914, T25934.
Thanks sam and simon for the help on this patch.
Co-authored-by: sheaf <sam.derbyshire(a)gmail.com>
- - - - -
386f1854 by Teo Camarasu at 2025-04-17T04:31:55-04:00
template-haskell: Remove `addrToByteArrayName` and `addrToByteArray`
These were part of the implementation of the `Lift ByteArray` instance and were errornously exported because this module lacked an explicit export list. They have no usages on Hackage.
Resolves #24782
- - - - -
b96e2f77 by Sylvain Henry at 2025-04-18T20:46:33-04:00
RTS: remove target info and fix host info (#24058)
The RTS isn't a compiler, hence it doesn't have a target and we remove
the reported target info displayed by "+RTS --info". We also fix the
host info displayed by "+RTS --info": the host of the RTS is the
RTS-building compiler's target, not the compiler's host (wrong when
doing cross-compilation).
- - - - -
6d9965f4 by Sylvain Henry at 2025-04-18T20:46:33-04:00
RTS: remove build info
As per the discussion in !13967, there is no reason to tag the RTS with
information about the build platform.
- - - - -
d52e9b3f by Vladislav Zavialov at 2025-04-18T20:47:15-04:00
Diagnostics: remove the KindMismatch constructor (#25957)
The KindMismatch constructor was only used as an intermediate
representation in pretty-printing.
Its removal addresses a problem detected by the "codes" test case:
[GHC-89223] is untested (constructor = KindMismatch)
In a concious deviation from the usual procedure, the error code
GHC-89223 is removed entirely rather than marked as Outdated.
The reason is that it never was user-facing in the first place.
- - - - -
e2f2f9d0 by Vladislav Zavialov at 2025-04-20T10:53:39-04:00
Add name for -Wunusable-unpack-pragmas
This warning had no name or flag and was triggered unconditionally.
Now it is part of -Wdefault.
In GHC.Tc.TyCl.tcTyClGroupsPass's strict mode, we now have to
force-enable this warning to ensure that detection of flawed groups
continues to work even if the user disables the warning with the
-Wno-unusable-unpack-pragmas option. Test case: T3990c
Also, the misnamed BackpackUnpackAbstractType is now called
UnusableUnpackPragma.
- - - - -
6caa6508 by Adam Gundry at 2025-04-20T10:54:22-04:00
Fix specialisation of incoherent instances (fixes #25883)
GHC normally assumes that class constraints are canonical, meaning that
the specialiser is allowed to replace one dictionary argument with another
provided that they have the same type. The `-fno-specialise-incoherents`
flag alters INCOHERENT instance definitions so that they will prevent
specialisation in some cases, by inserting `nospec`.
This commit fixes a bug in 7124e4ad76d98f1fc246ada4fd7bf64413ff2f2e, which
treated some INCOHERENT instance matches as if `-fno-specialise-incoherents`
was in effect, thereby unnecessarily preventing specialisation. In addition
it updates the relevant `Note [Rules for instance lookup]` and adds a new
`Note [Canonicity for incoherent matches]`.
- - - - -
0426fd6c by Adam Gundry at 2025-04-20T10:54:23-04:00
Add regression test for #23429
- - - - -
eec96527 by Adam Gundry at 2025-04-20T10:54:23-04:00
user's guide: update specification of overlapping/incoherent instances
The description of the instance resolution algorithm in the user's
guide was slightly out of date, because it mentioned in-scope given
constraints only at the end, whereas the implementation checks for
their presence before any of the other steps.
This also adds a warning to the user's guide about the impact of
incoherent instances on specialisation, and more clearly documents
some of the other effects of `-XIncoherentInstances`.
- - - - -
a00eeaec by Matthew Craven at 2025-04-20T10:55:03-04:00
Fix bytecode generation for `tagToEnum# <LITERAL>`
Fixes #25975.
- - - - -
2e204269 by Andreas Klebinger at 2025-04-22T12:20:41+02:00
Simplifier: Constant fold invald tagToEnum# calls to bottom expr.
When applying tagToEnum# to a out-of-range value it's best to simply
constant fold it to a bottom expression. That potentially allows more
dead code elimination and makes debugging easier.
Fixes #25976
- - - - -
7250fc0c by Matthew Pickering at 2025-04-22T16:24:04-04:00
Move -fno-code note into Downsweep module
This note was left behind when all the code which referred to it was
moved into the GHC.Driver.Downsweep module
- - - - -
d2dc89b4 by Matthew Pickering at 2025-04-22T16:24:04-04:00
Apply editing notes to Note [-fno-code mode] suggested by sheaf
These notes were suggested in https://gitlab.haskell.org/ghc/ghc/-/merge_requests/14241
- - - - -
91564daf by Matthew Pickering at 2025-04-24T00:29:02-04:00
ghci: Use loadInterfaceForModule rather than loadSrcInterface in mkTopLevEnv
loadSrcInterface takes a user given `ModuleName` and resolves it to the
module which needs to be loaded (taking into account module
renaming/visibility etc).
loadInterfaceForModule takes a specific module and loads it.
The modules in `ImpDeclSpec` have already been resolved to the actual
module to get the information from during renaming. Therefore we just
need to fetch the precise interface from disk (and not attempt to rename
it again).
Fixes #25951
- - - - -
2e0c07ab by Simon Peyton Jones at 2025-04-24T00:29:43-04:00
Test for #23298
- - - - -
0eef99b0 by Sven Tennie at 2025-04-24T07:34:36-04:00
RV64: Introduce J instruction (non-local jumps) and don't deallocate stack slots for J_TBL (#25738)
J_TBL result in local jumps, there should not deallocate stack slots
(see Note [extra spill slots].)
J is for non-local jumps, these may need to deallocate stack slots.
- - - - -
1bd3d13e by fendor at 2025-04-24T07:35:17-04:00
Add `UnitId` to `EvalBreakpoint`
The `EvalBreakpoint` is used to communicate that a breakpoint was
encountered during code evaluation.
This `EvalBreakpoint` needs to be converted to an `InternalBreakpointId`
which stores a `Module` to uniquely find the correct `Module` in the
Home Package Table.
The `EvalBreakpoint` used to store only a `ModuleName` which is then
converted to a `Module` based on the currently active home unit.
This is incorrect in the face of multiple home units, the break point
could be in an entirely other home unit!
To fix this, we additionally store the `UnitId` of the `Module` in
`EvalBreakpoint` to later reconstruct the correct `Module`
All of the changes are the consequence of extending `EvalBreakpoint`
with the additional `ShortByteString` of the `UnitId`.
For performance reasons, we store the `ShortByteString` backing the
`UnitId` directly, avoiding marshalling overhead.
- - - - -
fe6ed8d9 by Sylvain Henry at 2025-04-24T18:04:12-04:00
Doc: add doc for JS interruptible calling convention (#24444)
- - - - -
6111c5e4 by Ben Gamari at 2025-04-24T18:04:53-04:00
compiler: Ensure that Panic.Plain.assertPanic' provides callstack
In 36cddd2ce1a3bc62ea8a1307d8bc6006d54109cf @alt-romes removed CallStack
output from `GHC.Utils.Panic.Plain.assertPanic'`. While this output is
redundant due to the exception backtrace proposal, we may be
bootstrapping with a compiler which does not yet include this machinery.
Reintroduce the output for now.
Fixes #25898.
- - - - -
217caad1 by Matthew Pickering at 2025-04-25T18:58:42+01:00
Implement Explicit Level Imports for Template Haskell
This commit introduces the `ExplicitLevelImports` and
`ImplicitStagePersistence` language extensions as proposed in GHC
Proposal #682.
Key Features
------------
- `ExplicitLevelImports` adds two new import modifiers - `splice` and
`quote` - allowing precise control over the level at which imported
identifiers are available
- `ImplicitStagePersistence` (enabled by default) preserves existing
path-based cross-stage persistence behavior
- `NoImplicitStagePersistence` disables implicit cross-stage
persistence, requiring explicit level imports
Benefits
--------
- Improved compilation performance by reducing unnecessary code generation
- Enhanced IDE experience with faster feedback in `-fno-code` mode
- Better dependency tracking by distinguishing compile-time and runtime dependencies
- Foundation for future cross-compilation improvements
This implementation enables the separation of modules needed at
compile-time from those needed at runtime, allowing for more efficient
compilation pipelines and clearer code organization in projects using
Template Haskell.
Implementation Notes
--------------------
The level which a name is availble at is stored in the 'GRE', in the normal
GlobalRdrEnv. The function `greLevels` returns the levels which a specific GRE
is imported at. The level information for a 'Name' is computed by `getCurrentAndBindLevel`.
The level validity is checked by `checkCrossLevelLifting`.
Instances are checked by `checkWellLevelledDFun`, which computes the level an
instance by calling `checkWellLevelledInstanceWhat`, which sees what is
available at by looking at the module graph.
Modifications to downsweep
--------------------------
Code generation is now only enabled for modules which are needed at
compile time.
See the Note [-fno-code mode] for more information.
Uniform error messages for level errors
---------------------------------------
All error messages to do with levels are now reported uniformly using
the `TcRnBadlyStaged` constructor.
Error messages are uniformly reported in terms of levels.
0 - top-level
1 - quote level
-1 - splice level
The only level hard-coded into the compiler is the top-level in
GHC.Types.ThLevelIndex.topLevelIndex.
Uniformly refer to levels and stages
------------------------------------
There was much confusion about levels vs stages in the compiler.
A level is a semantic concept, used by the typechecker to ensure a
program can be evaluated in a well-staged manner.
A stage is an operational construct, program evaluation proceeds in
stages.
Deprecate -Wbadly-staged-types
------------------------------
`-Wbadly-staged-types` is deprecated in favour of `-Wbadly-levelled-types`.
Lift derivation changed
-----------------------
Derived lift instances will now not generate code with expression
quotations.
Before:
```
data A = A Int deriving Lift
=>
lift (A x) = [| A $(lift x) |]
```
After:
```
lift (A x) = conE 'A `appE` (lift x)
```
This is because if you attempt to derive `Lift` in a module where
`NoImplicitStagePersistence` is enabled, you would get an infinite loop
where a constructor was attempted to be persisted using the instance you
are currently defining.
GHC API Changes
---------------
The ModuleGraph now contains additional information about the type of
the edges (normal, quote or splice) between modules. This is abstracted
using the `ModuleGraphEdge` data type.
Fixes #25828
-------------------------
Metric Increase:
MultiLayerModulesTH_Make
-------------------------
- - - - -
7641a74a by Simon Peyton Jones at 2025-04-26T22:05:19-04:00
Get a decent MatchContext for pattern synonym bindings
In particular when we have a pattern binding
K p1 .. pn = rhs
where K is a pattern synonym. (It might be nested.)
This small MR fixes #25995. It's a tiny fix, to an error message,
removing an always-dubious `unkSkol`.
The bug report was in the context of horde-ad, a big program,
and I didn't manage to make a small repro case quickly. I decided
not to bother further.
- - - - -
ce616f49 by Simon Peyton Jones at 2025-04-27T21:10:25+01:00
Fix infelicities in the Specialiser
On the way to #23109 (unary classes) I discovered some infelicities
(or maybe tiny bugs, I forget) in the type-class specialiser.
I also tripped over #25965, an outright bug in the rule matcher
Specifically:
* Refactor: I enhanced `wantCallsFor`, whih previously always said
`True`, to discard calls of class-ops, data constructors etc. This is
a bit more efficient; and it means we don't need to worry about
filtering them out later.
* Fix: I tidied up some tricky logic that eliminated redundant
specialisations. It wasn't working correctly. See the expanded
Note [Specialisations already covered], and
(MP3) in Note [Specialising polymorphic dictionaries].
See also the new top-level `alreadyCovered`
function, which now goes via `GHC.Core.Rules.ruleLhsIsMoreSpecific`
I also added a useful Note [The (CI-KEY) invariant]
* Fix #25965: fixed a tricky bug in the `go_fam_fam` in
`GHC.Core.Unify.uVarOrFam`, which allows matching to succeed
without binding all type varibles.
I enhanced Note [Apartness and type families] some more
* #25703. This ticket "just works" with -fpolymorphic-specialisation;
but I was surprised that it worked! In this MR I added documentation
to Note [Interesting dictionary arguments] to explain; and tests to
ensure it stays fixed.
- - - - -
22d11fa8 by Simon Peyton Jones at 2025-04-28T18:05:19-04:00
Track rewriter sets more accurately in constraint solving
The key change, which fixed #25440, is to call `recordRewriter` in
GHC.Tc.Solver.Rewrite.rewrite_exact_fam_app. This missing call meant
that we were secretly rewriting a Wanted with a Wanted, but not really
noticing; and that led to a very bad error message, as you can see
in the ticket.
But of course that led me into rabbit hole of other refactoring around
the RewriteSet code:
* Improve Notes [Wanteds rewrite Wanteds]
* Zonk the RewriterSet in `zonkCtEvidence` rather than only in GHC.Tc.Errors.
This is tidier anyway (e.g. de-clutters debug output), and helps with the
next point.
* In GHC.Tc.Solver.Equality.inertsCanDischarge, don't replace a constraint
with no rewriters with an equal constraint that has many. See
See (CE4) in Note [Combining equalities]
* Move zonkRewriterSet and friends from GHC.Tc.Zonk.Type into
GHC.Tc.Zonk.TcType, where they properly belong.
A handful of tests get better error messages.
For some reason T24984 gets 12% less compiler allocation -- good
Metric Decrease:
T24984
- - - - -
6467d61e by Brandon Chinn at 2025-04-29T18:36:03-04:00
Fix lexing "\^\" (#25937)
This broke in the refactor in !13128, where the old code parsed escape
codes and collapsed string gaps at the same time, but the new code
collapsed gaps first, then resolved escape codes. The new code used a
naive heuristic to skip escaped backslashes, but didn't account for
"\^\".
- - - - -
99868a86 by Jens Petersen at 2025-04-29T18:36:44-04:00
hadrian: default selftest to disabled
- - - - -
aba2a4a5 by Zubin Duggal at 2025-04-30T06:35:59-04:00
get-win32-tarballs.py: List tarball files to be downloaded if we cannot find them
Fixes #25929
- - - - -
d99a617b by Ben Gamari at 2025-04-30T06:36:40-04:00
Move Data ModuleName instance to Language.Haskell.Syntax.Module.Name
Fixes #25968.
- - - - -
3aa60167 by Rodrigo Mesquita at 2025-05-02T15:52:56+01:00
Refactor mkTopLevImportedEnv out of mkTopLevEnv
This makes the code clearer and allows the top-level import context to
be fetched directly from the HomeModInfo through the API (e.g. useful
for the debugger).
- - - - -
d5865833 by Rodrigo Mesquita at 2025-05-02T15:52:57+01:00
Export sizeOccEnv from GHC.Types.Name.Occurrence
Counts the number of OccNames in an OccEnv
- - - - -
402 changed files:
- compiler/GHC.hs
- compiler/GHC/ByteCode/Asm.hs
- compiler/GHC/ByteCode/Instr.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/CmmToAsm/RV64/CodeGen.hs
- compiler/GHC/CmmToAsm/RV64/Instr.hs
- compiler/GHC/CmmToAsm/RV64/Ppr.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/InstEnv.hs
- compiler/GHC/Core/Opt/ConstantFold.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Data/Graph/Directed/Reachability.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Errors/Ppr.hs
- compiler/GHC/Driver/Errors/Types.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeAction.hs
- compiler/GHC/Driver/MakeFile.hs
- + compiler/GHC/Driver/Messager.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline.hs-boot
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/String.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Interpreter.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Utils.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Default.hs
- compiler/GHC/Tc/Gen/Export.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Plugin.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Types/TH.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Concrete.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/DefaultEnv.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Name/Occurrence.hs
- compiler/GHC/Types/Name/Reader.hs
- + compiler/GHC/Types/ThLevelIndex.hs
- compiler/GHC/Unit/External.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Home/PackageTable.hs
- compiler/GHC/Unit/Module/Deps.hs
- − compiler/GHC/Unit/Module/External/Graph.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/Imported.hs
- compiler/GHC/Unit/Module/ModNodeKey.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- + compiler/GHC/Unit/Module/Stage.hs
- compiler/GHC/Unit/Types.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/GHC/Utils/Panic/Plain.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- + compiler/Language/Haskell/Syntax/ImpExp/IsBoot.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- compiler/ghc.cabal.in
- configure.ac
- docs/users_guide/9.14.1-notes.rst
- docs/users_guide/exts/control.rst
- docs/users_guide/exts/instances.rst
- docs/users_guide/exts/template_haskell.rst
- docs/users_guide/javascript.rst
- docs/users_guide/phases.rst
- docs/users_guide/using-warnings.rst
- ghc/GHCi/UI.hs
- hadrian/README.md
- hadrian/hadrian.cabal
- hadrian/src/Settings/Packages.hs
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- − libraries/base/src/GHC/ExecutionStack/Internal.hs
- − libraries/base/src/GHC/TypeLits/Internal.hs
- − libraries/base/src/GHC/TypeNats/Internal.hs
- libraries/base/tests/IO/Makefile
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- libraries/ghci/GHCi/Message.hs
- libraries/ghci/GHCi/Run.hs
- libraries/template-haskell/Language/Haskell/TH/Syntax.hs
- libraries/template-haskell/changelog.md
- m4/fp_setup_windows_toolchain.m4
- rts/Exception.cmm
- rts/Interpreter.c
- rts/RtsUtils.c
- testsuite/ghc-config/ghc-config.hs
- testsuite/tests/ado/ado004.stderr
- testsuite/tests/annotations/should_fail/annfail03.stderr
- testsuite/tests/annotations/should_fail/annfail04.stderr
- testsuite/tests/annotations/should_fail/annfail06.stderr
- testsuite/tests/annotations/should_fail/annfail09.stderr
- + testsuite/tests/bytecode/T25975.hs
- + testsuite/tests/bytecode/T25975.stdout
- testsuite/tests/bytecode/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- + testsuite/tests/default/T25912.hs
- + testsuite/tests/default/T25912.stdout
- + testsuite/tests/default/T25912_helper.hs
- + testsuite/tests/default/T25914.hs
- + testsuite/tests/default/T25934.hs
- testsuite/tests/default/all.T
- testsuite/tests/default/default-fail03.stderr
- testsuite/tests/dependent/should_compile/T14729.stderr
- testsuite/tests/dependent/should_compile/T15743.stderr
- testsuite/tests/dependent/should_compile/T15743e.stderr
- testsuite/tests/deriving/should_compile/T14682.stderr
- testsuite/tests/determinism/determ021/determ021.stdout
- testsuite/tests/diagnostic-codes/codes.stdout
- + testsuite/tests/driver/T4437.stdout
- testsuite/tests/driver/json2.stderr
- testsuite/tests/gadt/T19847a.stderr
- + testsuite/tests/gadt/T23298.hs
- + testsuite/tests/gadt/T23298.stderr
- testsuite/tests/gadt/all.T
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- + testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.hs
- + testsuite/tests/ghc-api/fixed-nodes/InterfaceModuleGraph.stdout
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/ghc-api/fixed-nodes/all.T
- + testsuite/tests/ghci/scripts/GhciPackageRename.hs
- + testsuite/tests/ghci/scripts/GhciPackageRename.script
- + testsuite/tests/ghci/scripts/GhciPackageRename.stdout
- testsuite/tests/ghci/scripts/all.T
- testsuite/tests/indexed-types/should_compile/T15711.stderr
- testsuite/tests/indexed-types/should_compile/T15852.stderr
- testsuite/tests/indexed-types/should_compile/T3017.stderr
- testsuite/tests/indexed-types/should_fail/T3330c.stderr
- testsuite/tests/indexed-types/should_fail/T4174.stderr
- testsuite/tests/indexed-types/should_fail/T8227.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- testsuite/tests/linters/notes.stdout
- testsuite/tests/module/mod185.stderr
- testsuite/tests/module/mod58.stderr
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- + testsuite/tests/parser/should_run/T25937.hs
- + testsuite/tests/parser/should_run/T25937.stdout
- testsuite/tests/parser/should_run/all.T
- + testsuite/tests/parser/should_run/parser_unit_tests.hs
- testsuite/tests/partial-sigs/should_compile/ADT.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr1.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr2.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr3.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr4.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr5.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr6.stderr
- testsuite/tests/partial-sigs/should_compile/BoolToBool.stderr
- testsuite/tests/partial-sigs/should_compile/DataFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/Defaulting1MROn.stderr
- testsuite/tests/partial-sigs/should_compile/Defaulting2MROff.stderr
- testsuite/tests/partial-sigs/should_compile/Defaulting2MROn.stderr
- testsuite/tests/partial-sigs/should_compile/Either.stderr
- testsuite/tests/partial-sigs/should_compile/EqualityConstraint.stderr
- testsuite/tests/partial-sigs/should_compile/Every.stderr
- testsuite/tests/partial-sigs/should_compile/EveryNamed.stderr
- testsuite/tests/partial-sigs/should_compile/ExpressionSig.stderr
- testsuite/tests/partial-sigs/should_compile/ExpressionSigNamed.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints1.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints2.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints3.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraNumAMROff.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraNumAMROn.stderr
- testsuite/tests/partial-sigs/should_compile/Forall1.stderr
- testsuite/tests/partial-sigs/should_compile/GenNamed.stderr
- testsuite/tests/partial-sigs/should_compile/HigherRank1.stderr
- testsuite/tests/partial-sigs/should_compile/HigherRank2.stderr
- testsuite/tests/partial-sigs/should_compile/LocalDefinitionBug.stderr
- testsuite/tests/partial-sigs/should_compile/Meltdown.stderr
- testsuite/tests/partial-sigs/should_compile/MonoLocalBinds.stderr
- testsuite/tests/partial-sigs/should_compile/NamedTyVar.stderr
- testsuite/tests/partial-sigs/should_compile/NamedWildcardInDataFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/NamedWildcardInTypeFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/ParensAroundContext.stderr
- testsuite/tests/partial-sigs/should_compile/PatBind.stderr
- testsuite/tests/partial-sigs/should_compile/PatBind2.stderr
- testsuite/tests/partial-sigs/should_compile/PatternSig.stderr
- testsuite/tests/partial-sigs/should_compile/Recursive.stderr
- testsuite/tests/partial-sigs/should_compile/ScopedNamedWildcards.stderr
- testsuite/tests/partial-sigs/should_compile/ScopedNamedWildcardsGood.stderr
- testsuite/tests/partial-sigs/should_compile/ShowNamed.stderr
- testsuite/tests/partial-sigs/should_compile/SimpleGen.stderr
- testsuite/tests/partial-sigs/should_compile/SkipMany.stderr
- testsuite/tests/partial-sigs/should_compile/SomethingShowable.stderr
- testsuite/tests/partial-sigs/should_compile/TypeFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/Uncurry.stderr
- testsuite/tests/partial-sigs/should_compile/UncurryNamed.stderr
- testsuite/tests/partial-sigs/should_compile/WarningWildcardInstantiations.stderr
- testsuite/tests/plugins/defaulting-plugin/DefaultLifted.hs
- testsuite/tests/polykinds/T15592.stderr
- testsuite/tests/polykinds/T15592b.stderr
- testsuite/tests/printer/T18052a.stderr
- testsuite/tests/quasiquotation/qq001/qq001.stderr
- testsuite/tests/quasiquotation/qq002/qq002.stderr
- testsuite/tests/quasiquotation/qq003/qq003.stderr
- testsuite/tests/quasiquotation/qq004/qq004.stderr
- + testsuite/tests/quotes/T5721.stderr
- testsuite/tests/roles/should_compile/Roles1.stderr
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles2.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/roles/should_compile/T8958.stderr
- testsuite/tests/showIface/DocsInHiFile1.stdout
- testsuite/tests/showIface/DocsInHiFileTH.stdout
- testsuite/tests/showIface/HaddockIssue849.stdout
- testsuite/tests/showIface/HaddockOpts.stdout
- testsuite/tests/showIface/HaddockSpanIssueT24378.stdout
- testsuite/tests/showIface/LanguageExts.stdout
- testsuite/tests/showIface/MagicHashInHaddocks.stdout
- testsuite/tests/showIface/NoExportList.stdout
- testsuite/tests/showIface/PragmaDocs.stdout
- testsuite/tests/showIface/ReExports.stdout
- testsuite/tests/simplCore/should_compile/Makefile
- testsuite/tests/simplCore/should_compile/T23307c.stderr
- + testsuite/tests/simplCore/should_compile/T25703.hs
- + testsuite/tests/simplCore/should_compile/T25703.stderr
- + testsuite/tests/simplCore/should_compile/T25703a.hs
- + testsuite/tests/simplCore/should_compile/T25703a.stderr
- + testsuite/tests/simplCore/should_compile/T25883.hs
- + testsuite/tests/simplCore/should_compile/T25883.substr-simpl
- + testsuite/tests/simplCore/should_compile/T25883b.hs
- + testsuite/tests/simplCore/should_compile/T25883b.substr-simpl
- + testsuite/tests/simplCore/should_compile/T25883c.hs
- + testsuite/tests/simplCore/should_compile/T25883c.substr-simpl
- + testsuite/tests/simplCore/should_compile/T25883d.hs
- + testsuite/tests/simplCore/should_compile/T25883d.stderr
- + testsuite/tests/simplCore/should_compile/T25883d_import.hs
- + testsuite/tests/simplCore/should_compile/T25965.hs
- + testsuite/tests/simplCore/should_compile/T25976.hs
- + testsuite/tests/simplCore/should_compile/T3990c.hs
- + testsuite/tests/simplCore/should_compile/T3990c.stdout
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_fail/T25672.stderr
- + testsuite/tests/simplCore/should_run/T23429.hs
- + testsuite/tests/simplCore/should_run/T23429.stdout
- testsuite/tests/simplCore/should_run/all.T
- + testsuite/tests/splice-imports/ClassA.hs
- + testsuite/tests/splice-imports/InstanceA.hs
- + testsuite/tests/splice-imports/Makefile
- + testsuite/tests/splice-imports/SI01.hs
- + testsuite/tests/splice-imports/SI01A.hs
- + testsuite/tests/splice-imports/SI02.hs
- + testsuite/tests/splice-imports/SI03.hs
- + testsuite/tests/splice-imports/SI03.stderr
- + testsuite/tests/splice-imports/SI04.hs
- + testsuite/tests/splice-imports/SI05.hs
- + testsuite/tests/splice-imports/SI05.stderr
- + testsuite/tests/splice-imports/SI05A.hs
- + testsuite/tests/splice-imports/SI06.hs
- + testsuite/tests/splice-imports/SI07.hs
- + testsuite/tests/splice-imports/SI07.stderr
- + testsuite/tests/splice-imports/SI07A.hs
- + testsuite/tests/splice-imports/SI08.hs
- + testsuite/tests/splice-imports/SI08.stderr
- + testsuite/tests/splice-imports/SI08_oneshot.stderr
- + testsuite/tests/splice-imports/SI09.hs
- + testsuite/tests/splice-imports/SI10.hs
- + testsuite/tests/splice-imports/SI13.hs
- + testsuite/tests/splice-imports/SI14.hs
- + testsuite/tests/splice-imports/SI14.stderr
- + testsuite/tests/splice-imports/SI15.hs
- + testsuite/tests/splice-imports/SI15.stderr
- + testsuite/tests/splice-imports/SI16.hs
- + testsuite/tests/splice-imports/SI16.stderr
- + testsuite/tests/splice-imports/SI17.hs
- + testsuite/tests/splice-imports/SI18.hs
- + testsuite/tests/splice-imports/SI18.stderr
- + testsuite/tests/splice-imports/SI19.hs
- + testsuite/tests/splice-imports/SI19A.hs
- + testsuite/tests/splice-imports/SI20.hs
- + testsuite/tests/splice-imports/SI20.stderr
- + testsuite/tests/splice-imports/SI21.hs
- + testsuite/tests/splice-imports/SI21.stderr
- + testsuite/tests/splice-imports/SI22.hs
- + testsuite/tests/splice-imports/SI22.stderr
- + testsuite/tests/splice-imports/SI23.hs
- + testsuite/tests/splice-imports/SI23A.hs
- + testsuite/tests/splice-imports/SI24.hs
- + testsuite/tests/splice-imports/SI25.hs
- + testsuite/tests/splice-imports/SI25.stderr
- + testsuite/tests/splice-imports/SI25Helper.hs
- + testsuite/tests/splice-imports/SI26.hs
- + testsuite/tests/splice-imports/SI27.hs
- + testsuite/tests/splice-imports/SI27.stderr
- + testsuite/tests/splice-imports/SI28.hs
- + testsuite/tests/splice-imports/SI28.stderr
- + testsuite/tests/splice-imports/SI29.hs
- + testsuite/tests/splice-imports/SI29.stderr
- + testsuite/tests/splice-imports/SI30.script
- + testsuite/tests/splice-imports/SI30.stdout
- + testsuite/tests/splice-imports/SI31.script
- + testsuite/tests/splice-imports/SI31.stderr
- + testsuite/tests/splice-imports/SI32.script
- + testsuite/tests/splice-imports/SI32.stdout
- + testsuite/tests/splice-imports/SI33.script
- + testsuite/tests/splice-imports/SI33.stdout
- + testsuite/tests/splice-imports/SI34.hs
- + testsuite/tests/splice-imports/SI34.stderr
- + testsuite/tests/splice-imports/SI34M1.hs
- + testsuite/tests/splice-imports/SI34M2.hs
- + testsuite/tests/splice-imports/SI35.hs
- + testsuite/tests/splice-imports/SI35A.hs
- + testsuite/tests/splice-imports/SI36.hs
- + testsuite/tests/splice-imports/SI36.stderr
- + testsuite/tests/splice-imports/SI36_A.hs
- + testsuite/tests/splice-imports/SI36_B1.hs
- + testsuite/tests/splice-imports/SI36_B2.hs
- + testsuite/tests/splice-imports/SI36_B3.hs
- + testsuite/tests/splice-imports/SI36_C1.hs
- + testsuite/tests/splice-imports/SI36_C2.hs
- + testsuite/tests/splice-imports/SI36_C3.hs
- + testsuite/tests/splice-imports/all.T
- testsuite/tests/th/T16976z.stderr
- testsuite/tests/th/T17820a.stderr
- testsuite/tests/th/T17820b.stderr
- testsuite/tests/th/T17820c.stderr
- testsuite/tests/th/T17820d.stderr
- testsuite/tests/th/T17820e.stderr
- testsuite/tests/th/T21547.stderr
- testsuite/tests/th/T23829_hasty.stderr
- testsuite/tests/th/T23829_hasty_b.stderr
- testsuite/tests/th/T23829_tardy.ghc.stderr
- testsuite/tests/th/T5795.stderr
- testsuite/tests/th/TH_Roles2.stderr
- testsuite/tests/typecheck/should_compile/T12763.stderr
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- testsuite/tests/typecheck/should_compile/T21023.stderr
- testsuite/tests/typecheck/should_compile/T25266a.stderr
- testsuite/tests/typecheck/should_compile/T7050.stderr
- testsuite/tests/typecheck/should_fail/T18851.stderr
- testsuite/tests/typecheck/should_fail/T3966.stderr
- + testsuite/tests/typecheck/should_fail/T3966b.hs
- + testsuite/tests/typecheck/should_fail/T3966b.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/unboxedsums/unpack_sums_5.stderr
- utils/check-exact/ExactPrint.hs
- utils/count-deps/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/fd7f3f11aa945f910a5f41ef50ea27…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/fd7f3f11aa945f910a5f41ef50ea27…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/fendor/ghci-multiple-home-units] 13 commits: Doc: add doc for JS interruptible calling convention (#24444)
by Hannes Siebenhandl (@fendor) 02 May '25
by Hannes Siebenhandl (@fendor) 02 May '25
02 May '25
Hannes Siebenhandl pushed to branch wip/fendor/ghci-multiple-home-units at Glasgow Haskell Compiler / GHC
Commits:
fe6ed8d9 by Sylvain Henry at 2025-04-24T18:04:12-04:00
Doc: add doc for JS interruptible calling convention (#24444)
- - - - -
6111c5e4 by Ben Gamari at 2025-04-24T18:04:53-04:00
compiler: Ensure that Panic.Plain.assertPanic' provides callstack
In 36cddd2ce1a3bc62ea8a1307d8bc6006d54109cf @alt-romes removed CallStack
output from `GHC.Utils.Panic.Plain.assertPanic'`. While this output is
redundant due to the exception backtrace proposal, we may be
bootstrapping with a compiler which does not yet include this machinery.
Reintroduce the output for now.
Fixes #25898.
- - - - -
217caad1 by Matthew Pickering at 2025-04-25T18:58:42+01:00
Implement Explicit Level Imports for Template Haskell
This commit introduces the `ExplicitLevelImports` and
`ImplicitStagePersistence` language extensions as proposed in GHC
Proposal #682.
Key Features
------------
- `ExplicitLevelImports` adds two new import modifiers - `splice` and
`quote` - allowing precise control over the level at which imported
identifiers are available
- `ImplicitStagePersistence` (enabled by default) preserves existing
path-based cross-stage persistence behavior
- `NoImplicitStagePersistence` disables implicit cross-stage
persistence, requiring explicit level imports
Benefits
--------
- Improved compilation performance by reducing unnecessary code generation
- Enhanced IDE experience with faster feedback in `-fno-code` mode
- Better dependency tracking by distinguishing compile-time and runtime dependencies
- Foundation for future cross-compilation improvements
This implementation enables the separation of modules needed at
compile-time from those needed at runtime, allowing for more efficient
compilation pipelines and clearer code organization in projects using
Template Haskell.
Implementation Notes
--------------------
The level which a name is availble at is stored in the 'GRE', in the normal
GlobalRdrEnv. The function `greLevels` returns the levels which a specific GRE
is imported at. The level information for a 'Name' is computed by `getCurrentAndBindLevel`.
The level validity is checked by `checkCrossLevelLifting`.
Instances are checked by `checkWellLevelledDFun`, which computes the level an
instance by calling `checkWellLevelledInstanceWhat`, which sees what is
available at by looking at the module graph.
Modifications to downsweep
--------------------------
Code generation is now only enabled for modules which are needed at
compile time.
See the Note [-fno-code mode] for more information.
Uniform error messages for level errors
---------------------------------------
All error messages to do with levels are now reported uniformly using
the `TcRnBadlyStaged` constructor.
Error messages are uniformly reported in terms of levels.
0 - top-level
1 - quote level
-1 - splice level
The only level hard-coded into the compiler is the top-level in
GHC.Types.ThLevelIndex.topLevelIndex.
Uniformly refer to levels and stages
------------------------------------
There was much confusion about levels vs stages in the compiler.
A level is a semantic concept, used by the typechecker to ensure a
program can be evaluated in a well-staged manner.
A stage is an operational construct, program evaluation proceeds in
stages.
Deprecate -Wbadly-staged-types
------------------------------
`-Wbadly-staged-types` is deprecated in favour of `-Wbadly-levelled-types`.
Lift derivation changed
-----------------------
Derived lift instances will now not generate code with expression
quotations.
Before:
```
data A = A Int deriving Lift
=>
lift (A x) = [| A $(lift x) |]
```
After:
```
lift (A x) = conE 'A `appE` (lift x)
```
This is because if you attempt to derive `Lift` in a module where
`NoImplicitStagePersistence` is enabled, you would get an infinite loop
where a constructor was attempted to be persisted using the instance you
are currently defining.
GHC API Changes
---------------
The ModuleGraph now contains additional information about the type of
the edges (normal, quote or splice) between modules. This is abstracted
using the `ModuleGraphEdge` data type.
Fixes #25828
-------------------------
Metric Increase:
MultiLayerModulesTH_Make
-------------------------
- - - - -
7641a74a by Simon Peyton Jones at 2025-04-26T22:05:19-04:00
Get a decent MatchContext for pattern synonym bindings
In particular when we have a pattern binding
K p1 .. pn = rhs
where K is a pattern synonym. (It might be nested.)
This small MR fixes #25995. It's a tiny fix, to an error message,
removing an always-dubious `unkSkol`.
The bug report was in the context of horde-ad, a big program,
and I didn't manage to make a small repro case quickly. I decided
not to bother further.
- - - - -
ce616f49 by Simon Peyton Jones at 2025-04-27T21:10:25+01:00
Fix infelicities in the Specialiser
On the way to #23109 (unary classes) I discovered some infelicities
(or maybe tiny bugs, I forget) in the type-class specialiser.
I also tripped over #25965, an outright bug in the rule matcher
Specifically:
* Refactor: I enhanced `wantCallsFor`, whih previously always said
`True`, to discard calls of class-ops, data constructors etc. This is
a bit more efficient; and it means we don't need to worry about
filtering them out later.
* Fix: I tidied up some tricky logic that eliminated redundant
specialisations. It wasn't working correctly. See the expanded
Note [Specialisations already covered], and
(MP3) in Note [Specialising polymorphic dictionaries].
See also the new top-level `alreadyCovered`
function, which now goes via `GHC.Core.Rules.ruleLhsIsMoreSpecific`
I also added a useful Note [The (CI-KEY) invariant]
* Fix #25965: fixed a tricky bug in the `go_fam_fam` in
`GHC.Core.Unify.uVarOrFam`, which allows matching to succeed
without binding all type varibles.
I enhanced Note [Apartness and type families] some more
* #25703. This ticket "just works" with -fpolymorphic-specialisation;
but I was surprised that it worked! In this MR I added documentation
to Note [Interesting dictionary arguments] to explain; and tests to
ensure it stays fixed.
- - - - -
22d11fa8 by Simon Peyton Jones at 2025-04-28T18:05:19-04:00
Track rewriter sets more accurately in constraint solving
The key change, which fixed #25440, is to call `recordRewriter` in
GHC.Tc.Solver.Rewrite.rewrite_exact_fam_app. This missing call meant
that we were secretly rewriting a Wanted with a Wanted, but not really
noticing; and that led to a very bad error message, as you can see
in the ticket.
But of course that led me into rabbit hole of other refactoring around
the RewriteSet code:
* Improve Notes [Wanteds rewrite Wanteds]
* Zonk the RewriterSet in `zonkCtEvidence` rather than only in GHC.Tc.Errors.
This is tidier anyway (e.g. de-clutters debug output), and helps with the
next point.
* In GHC.Tc.Solver.Equality.inertsCanDischarge, don't replace a constraint
with no rewriters with an equal constraint that has many. See
See (CE4) in Note [Combining equalities]
* Move zonkRewriterSet and friends from GHC.Tc.Zonk.Type into
GHC.Tc.Zonk.TcType, where they properly belong.
A handful of tests get better error messages.
For some reason T24984 gets 12% less compiler allocation -- good
Metric Decrease:
T24984
- - - - -
6467d61e by Brandon Chinn at 2025-04-29T18:36:03-04:00
Fix lexing "\^\" (#25937)
This broke in the refactor in !13128, where the old code parsed escape
codes and collapsed string gaps at the same time, but the new code
collapsed gaps first, then resolved escape codes. The new code used a
naive heuristic to skip escaped backslashes, but didn't account for
"\^\".
- - - - -
99868a86 by Jens Petersen at 2025-04-29T18:36:44-04:00
hadrian: default selftest to disabled
- - - - -
aba2a4a5 by Zubin Duggal at 2025-04-30T06:35:59-04:00
get-win32-tarballs.py: List tarball files to be downloaded if we cannot find them
Fixes #25929
- - - - -
d99a617b by Ben Gamari at 2025-04-30T06:36:40-04:00
Move Data ModuleName instance to Language.Haskell.Syntax.Module.Name
Fixes #25968.
- - - - -
d639997e by fendor at 2025-05-02T16:49:58+02:00
Add testcases for GHCi multiple home units
Adds the following testcases:
* Evaluate code with a single home unit using 'initMulti' initialisation
logic
* More complicated testcase with multiple home units, testing reload
logic and code evaluation.
- - - - -
d2496ebb by fendor at 2025-05-02T16:49:58+02:00
Make GHCi commands compatible with multiple home units
FIXME: proper commit message
There is one metric increase in this commit:
-------------------------
Metric Increase:
T4029
-------------------------
It is an increase from 14.4 MB to 16.1 MB (+11.8%) which sounds like a
pretty big regression at first.
However, we argue this increase is solely caused by using more data
structures for managing multiple home units in the GHCi session.
In particular, due to the design decision of using three home units, the
base memory usage increases... but by how much?
A big contributor is the `UnitState`, of which we have three now, which
on its own 260 KB per instance. That makes an additional memory usage of
520 KB, already explaining a third of the overall memory usage increase.
FIXME: re-investigate what the remaining 1 MB is.
- - - - -
b8505b6c by fendor at 2025-05-02T16:49:58+02:00
FIXME: this test case can be fixed by exploiting internals
- - - - -
369 changed files:
- compiler/GHC.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Data/Graph/Directed/Reachability.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/ImpExp.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Tidy.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Errors/Ppr.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/String.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Splice.hs
- compiler/GHC/Rename/Unbound.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Runtime/Context.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/StgToByteCode.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Deriv/Generate.hs
- compiler/GHC/Tc/Deriv/Utils.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Plugin.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/LclEnv.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Types/TH.hs
- compiler/GHC/Tc/Utils/Backpack.hs
- compiler/GHC/Tc/Utils/Concrete.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/Error/Codes.hs
- compiler/GHC/Types/Name/Ppr.hs
- compiler/GHC/Types/Name/Reader.hs
- + compiler/GHC/Types/ThLevelIndex.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Home/PackageTable.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/Imported.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- + compiler/GHC/Unit/Module/Stage.hs
- compiler/GHC/Unit/Types.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/GHC/Utils/Panic/Plain.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- + compiler/Language/Haskell/Syntax/ImpExp/IsBoot.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- compiler/ghc.cabal.in
- docs/users_guide/exts/control.rst
- docs/users_guide/exts/template_haskell.rst
- docs/users_guide/javascript.rst
- docs/users_guide/phases.rst
- docs/users_guide/using-warnings.rst
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Info.hs
- ghc/GHCi/UI/Monad.hs
- ghc/Main.hs
- hadrian/README.md
- hadrian/hadrian.cabal
- libraries/base/tests/IO/Makefile
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- m4/fp_setup_windows_toolchain.m4
- testsuite/driver/testlib.py
- testsuite/tests/ado/ado004.stderr
- testsuite/tests/annotations/should_fail/annfail03.stderr
- testsuite/tests/annotations/should_fail/annfail04.stderr
- testsuite/tests/annotations/should_fail/annfail06.stderr
- testsuite/tests/annotations/should_fail/annfail09.stderr
- testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.stdout
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/dependent/should_compile/T14729.stderr
- testsuite/tests/dependent/should_compile/T15743.stderr
- testsuite/tests/dependent/should_compile/T15743e.stderr
- testsuite/tests/deriving/should_compile/T14682.stderr
- testsuite/tests/determinism/determ021/determ021.stdout
- + testsuite/tests/driver/T4437.stdout
- testsuite/tests/driver/T8526/T8526.stdout
- testsuite/tests/driver/fat-iface/fat014.stdout
- testsuite/tests/driver/json2.stderr
- testsuite/tests/driver/multipleHomeUnits/multiGHCi.stderr
- testsuite/tests/gadt/T19847a.stderr
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghc-api/annotations-literals/literals.hs
- testsuite/tests/ghc-api/annotations-literals/parsed.hs
- testsuite/tests/ghc-api/apirecomp001/myghc.hs
- testsuite/tests/ghc-api/fixed-nodes/FixedNodes.hs
- testsuite/tests/ghc-api/fixed-nodes/ModuleGraphInvariants.hs
- testsuite/tests/ghc-api/fixed-nodes/T1.hs
- + testsuite/tests/ghci.debugger/scripts/break031/Makefile
- + testsuite/tests/ghci.debugger/scripts/break031/a/A.hs
- + testsuite/tests/ghci.debugger/scripts/break031/all.T
- + testsuite/tests/ghci.debugger/scripts/break031/b/B.hs
- + testsuite/tests/ghci.debugger/scripts/break031/break031a.script
- + testsuite/tests/ghci.debugger/scripts/break031/break031a.stdout
- + testsuite/tests/ghci.debugger/scripts/break031/break031b.script
- + testsuite/tests/ghci.debugger/scripts/break031/break031b.stderr
- + testsuite/tests/ghci.debugger/scripts/break031/break031b.stdout
- + testsuite/tests/ghci.debugger/scripts/break031/unitA
- + testsuite/tests/ghci.debugger/scripts/break031/unitB
- testsuite/tests/ghci/linking/dyn/T3372.hs
- + testsuite/tests/ghci/prog-mhu001/Makefile
- + testsuite/tests/ghci/prog-mhu001/e/E.hs
- + testsuite/tests/ghci/prog-mhu001/prog-mhu001.T
- + testsuite/tests/ghci/prog-mhu001/prog-mhu001.script
- + testsuite/tests/ghci/prog-mhu001/prog-mhu001.stdout
- + testsuite/tests/ghci/prog-mhu001/unitE
- + testsuite/tests/ghci/prog-mhu002/Makefile
- + testsuite/tests/ghci/prog-mhu002/a/A.hs
- + testsuite/tests/ghci/prog-mhu002/b/B.hs
- + testsuite/tests/ghci/prog-mhu002/c/C.hs
- + testsuite/tests/ghci/prog-mhu002/d/Main.hs
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.T
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.script
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.stderr
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.stdout
- + testsuite/tests/ghci/prog-mhu002/unitA
- + testsuite/tests/ghci/prog-mhu002/unitB
- + testsuite/tests/ghci/prog-mhu002/unitC
- + testsuite/tests/ghci/prog-mhu002/unitD
- testsuite/tests/ghci/prog018/prog018.stdout
- testsuite/tests/ghci/scripts/T13869.stdout
- testsuite/tests/ghci/scripts/T13997.stdout
- testsuite/tests/ghci/scripts/T17669.stdout
- testsuite/tests/ghci/scripts/T18330.stdout
- testsuite/tests/ghci/scripts/T1914.stdout
- testsuite/tests/ghci/scripts/T20217.stdout
- testsuite/tests/ghci/scripts/T20587.stdout
- testsuite/tests/ghci/scripts/T21110.stderr
- testsuite/tests/ghci/scripts/T6105.stdout
- testsuite/tests/ghci/scripts/T8042.stdout
- testsuite/tests/ghci/scripts/T8042recomp.stdout
- testsuite/tests/ghci/scripts/ghci024.stdout
- testsuite/tests/ghci/scripts/ghci058.script
- testsuite/tests/ghci/should_run/TopEnvIface.stdout
- testsuite/tests/indexed-types/should_compile/T15711.stderr
- testsuite/tests/indexed-types/should_compile/T15852.stderr
- testsuite/tests/indexed-types/should_compile/T3017.stderr
- testsuite/tests/indexed-types/should_fail/T3330c.stderr
- testsuite/tests/indexed-types/should_fail/T4174.stderr
- testsuite/tests/indexed-types/should_fail/T8227.stderr
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- testsuite/tests/module/mod185.stderr
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- + testsuite/tests/parser/should_run/T25937.hs
- + testsuite/tests/parser/should_run/T25937.stdout
- testsuite/tests/parser/should_run/all.T
- + testsuite/tests/parser/should_run/parser_unit_tests.hs
- testsuite/tests/partial-sigs/should_compile/ADT.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr1.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr2.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr3.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr4.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr5.stderr
- testsuite/tests/partial-sigs/should_compile/AddAndOr6.stderr
- testsuite/tests/partial-sigs/should_compile/BoolToBool.stderr
- testsuite/tests/partial-sigs/should_compile/DataFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/Defaulting1MROn.stderr
- testsuite/tests/partial-sigs/should_compile/Defaulting2MROff.stderr
- testsuite/tests/partial-sigs/should_compile/Defaulting2MROn.stderr
- testsuite/tests/partial-sigs/should_compile/Either.stderr
- testsuite/tests/partial-sigs/should_compile/EqualityConstraint.stderr
- testsuite/tests/partial-sigs/should_compile/Every.stderr
- testsuite/tests/partial-sigs/should_compile/EveryNamed.stderr
- testsuite/tests/partial-sigs/should_compile/ExpressionSig.stderr
- testsuite/tests/partial-sigs/should_compile/ExpressionSigNamed.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints1.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints2.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraConstraints3.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraNumAMROff.stderr
- testsuite/tests/partial-sigs/should_compile/ExtraNumAMROn.stderr
- testsuite/tests/partial-sigs/should_compile/Forall1.stderr
- testsuite/tests/partial-sigs/should_compile/GenNamed.stderr
- testsuite/tests/partial-sigs/should_compile/HigherRank1.stderr
- testsuite/tests/partial-sigs/should_compile/HigherRank2.stderr
- testsuite/tests/partial-sigs/should_compile/LocalDefinitionBug.stderr
- testsuite/tests/partial-sigs/should_compile/Meltdown.stderr
- testsuite/tests/partial-sigs/should_compile/MonoLocalBinds.stderr
- testsuite/tests/partial-sigs/should_compile/NamedTyVar.stderr
- testsuite/tests/partial-sigs/should_compile/NamedWildcardInDataFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/NamedWildcardInTypeFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/ParensAroundContext.stderr
- testsuite/tests/partial-sigs/should_compile/PatBind.stderr
- testsuite/tests/partial-sigs/should_compile/PatBind2.stderr
- testsuite/tests/partial-sigs/should_compile/PatternSig.stderr
- testsuite/tests/partial-sigs/should_compile/Recursive.stderr
- testsuite/tests/partial-sigs/should_compile/ScopedNamedWildcards.stderr
- testsuite/tests/partial-sigs/should_compile/ScopedNamedWildcardsGood.stderr
- testsuite/tests/partial-sigs/should_compile/ShowNamed.stderr
- testsuite/tests/partial-sigs/should_compile/SimpleGen.stderr
- testsuite/tests/partial-sigs/should_compile/SkipMany.stderr
- testsuite/tests/partial-sigs/should_compile/SomethingShowable.stderr
- testsuite/tests/partial-sigs/should_compile/TypeFamilyInstanceLHS.stderr
- testsuite/tests/partial-sigs/should_compile/Uncurry.stderr
- testsuite/tests/partial-sigs/should_compile/UncurryNamed.stderr
- testsuite/tests/partial-sigs/should_compile/WarningWildcardInstantiations.stderr
- testsuite/tests/polykinds/T15592.stderr
- testsuite/tests/polykinds/T15592b.stderr
- testsuite/tests/printer/T18052a.stderr
- testsuite/tests/quasiquotation/T7918.hs
- testsuite/tests/quasiquotation/qq001/qq001.stderr
- testsuite/tests/quasiquotation/qq002/qq002.stderr
- testsuite/tests/quasiquotation/qq003/qq003.stderr
- testsuite/tests/quasiquotation/qq004/qq004.stderr
- + testsuite/tests/quotes/T5721.stderr
- testsuite/tests/roles/should_compile/Roles1.stderr
- testsuite/tests/roles/should_compile/Roles14.stderr
- testsuite/tests/roles/should_compile/Roles2.stderr
- testsuite/tests/roles/should_compile/Roles3.stderr
- testsuite/tests/roles/should_compile/Roles4.stderr
- testsuite/tests/roles/should_compile/T8958.stderr
- testsuite/tests/showIface/DocsInHiFile1.stdout
- testsuite/tests/showIface/DocsInHiFileTH.stdout
- testsuite/tests/showIface/HaddockIssue849.stdout
- testsuite/tests/showIface/HaddockOpts.stdout
- testsuite/tests/showIface/HaddockSpanIssueT24378.stdout
- testsuite/tests/showIface/LanguageExts.stdout
- testsuite/tests/showIface/MagicHashInHaddocks.stdout
- testsuite/tests/showIface/NoExportList.stdout
- testsuite/tests/showIface/PragmaDocs.stdout
- testsuite/tests/showIface/ReExports.stdout
- + testsuite/tests/simplCore/should_compile/T25703.hs
- + testsuite/tests/simplCore/should_compile/T25703.stderr
- + testsuite/tests/simplCore/should_compile/T25703a.hs
- + testsuite/tests/simplCore/should_compile/T25703a.stderr
- + testsuite/tests/simplCore/should_compile/T25965.hs
- testsuite/tests/simplCore/should_compile/all.T
- + testsuite/tests/splice-imports/ClassA.hs
- + testsuite/tests/splice-imports/InstanceA.hs
- + testsuite/tests/splice-imports/Makefile
- + testsuite/tests/splice-imports/SI01.hs
- + testsuite/tests/splice-imports/SI01A.hs
- + testsuite/tests/splice-imports/SI02.hs
- + testsuite/tests/splice-imports/SI03.hs
- + testsuite/tests/splice-imports/SI03.stderr
- + testsuite/tests/splice-imports/SI04.hs
- + testsuite/tests/splice-imports/SI05.hs
- + testsuite/tests/splice-imports/SI05.stderr
- + testsuite/tests/splice-imports/SI05A.hs
- + testsuite/tests/splice-imports/SI06.hs
- + testsuite/tests/splice-imports/SI07.hs
- + testsuite/tests/splice-imports/SI07.stderr
- + testsuite/tests/splice-imports/SI07A.hs
- + testsuite/tests/splice-imports/SI08.hs
- + testsuite/tests/splice-imports/SI08.stderr
- + testsuite/tests/splice-imports/SI08_oneshot.stderr
- + testsuite/tests/splice-imports/SI09.hs
- + testsuite/tests/splice-imports/SI10.hs
- + testsuite/tests/splice-imports/SI13.hs
- + testsuite/tests/splice-imports/SI14.hs
- + testsuite/tests/splice-imports/SI14.stderr
- + testsuite/tests/splice-imports/SI15.hs
- + testsuite/tests/splice-imports/SI15.stderr
- + testsuite/tests/splice-imports/SI16.hs
- + testsuite/tests/splice-imports/SI16.stderr
- + testsuite/tests/splice-imports/SI17.hs
- + testsuite/tests/splice-imports/SI18.hs
- + testsuite/tests/splice-imports/SI18.stderr
- + testsuite/tests/splice-imports/SI19.hs
- + testsuite/tests/splice-imports/SI19A.hs
- + testsuite/tests/splice-imports/SI20.hs
- + testsuite/tests/splice-imports/SI20.stderr
- + testsuite/tests/splice-imports/SI21.hs
- + testsuite/tests/splice-imports/SI21.stderr
- + testsuite/tests/splice-imports/SI22.hs
- + testsuite/tests/splice-imports/SI22.stderr
- + testsuite/tests/splice-imports/SI23.hs
- + testsuite/tests/splice-imports/SI23A.hs
- + testsuite/tests/splice-imports/SI24.hs
- + testsuite/tests/splice-imports/SI25.hs
- + testsuite/tests/splice-imports/SI25.stderr
- + testsuite/tests/splice-imports/SI25Helper.hs
- + testsuite/tests/splice-imports/SI26.hs
- + testsuite/tests/splice-imports/SI27.hs
- + testsuite/tests/splice-imports/SI27.stderr
- + testsuite/tests/splice-imports/SI28.hs
- + testsuite/tests/splice-imports/SI28.stderr
- + testsuite/tests/splice-imports/SI29.hs
- + testsuite/tests/splice-imports/SI29.stderr
- + testsuite/tests/splice-imports/SI30.script
- + testsuite/tests/splice-imports/SI30.stdout
- + testsuite/tests/splice-imports/SI31.script
- + testsuite/tests/splice-imports/SI31.stderr
- + testsuite/tests/splice-imports/SI32.script
- + testsuite/tests/splice-imports/SI32.stdout
- + testsuite/tests/splice-imports/SI33.script
- + testsuite/tests/splice-imports/SI33.stdout
- + testsuite/tests/splice-imports/SI34.hs
- + testsuite/tests/splice-imports/SI34.stderr
- + testsuite/tests/splice-imports/SI34M1.hs
- + testsuite/tests/splice-imports/SI34M2.hs
- + testsuite/tests/splice-imports/SI35.hs
- + testsuite/tests/splice-imports/SI35A.hs
- + testsuite/tests/splice-imports/SI36.hs
- + testsuite/tests/splice-imports/SI36.stderr
- + testsuite/tests/splice-imports/SI36_A.hs
- + testsuite/tests/splice-imports/SI36_B1.hs
- + testsuite/tests/splice-imports/SI36_B2.hs
- + testsuite/tests/splice-imports/SI36_B3.hs
- + testsuite/tests/splice-imports/SI36_C1.hs
- + testsuite/tests/splice-imports/SI36_C2.hs
- + testsuite/tests/splice-imports/SI36_C3.hs
- + testsuite/tests/splice-imports/all.T
- testsuite/tests/th/T16976z.stderr
- testsuite/tests/th/T17820a.stderr
- testsuite/tests/th/T17820b.stderr
- testsuite/tests/th/T17820c.stderr
- testsuite/tests/th/T17820d.stderr
- testsuite/tests/th/T17820e.stderr
- testsuite/tests/th/T21547.stderr
- testsuite/tests/th/T23829_hasty.stderr
- testsuite/tests/th/T23829_hasty_b.stderr
- testsuite/tests/th/T23829_tardy.ghc.stderr
- testsuite/tests/th/T5795.stderr
- testsuite/tests/th/TH_Roles2.stderr
- testsuite/tests/typecheck/should_compile/T12763.stderr
- testsuite/tests/typecheck/should_compile/T18406b.stderr
- testsuite/tests/typecheck/should_compile/T18529.stderr
- testsuite/tests/typecheck/should_compile/T21023.stderr
- testsuite/tests/typecheck/should_compile/T25266a.stderr
- testsuite/tests/typecheck/should_fail/T18851.stderr
- utils/check-exact/ExactPrint.hs
- utils/count-deps/Main.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2df3c7959d339547321804f1f7a459…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2df3c7959d339547321804f1f7a459…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/fendor/ghci-multiple-home-units] 3 commits: Add testcases for GHCi multiple home units
by Hannes Siebenhandl (@fendor) 02 May '25
by Hannes Siebenhandl (@fendor) 02 May '25
02 May '25
Hannes Siebenhandl pushed to branch wip/fendor/ghci-multiple-home-units at Glasgow Haskell Compiler / GHC
Commits:
18849d66 by fendor at 2025-05-02T11:17:09+02:00
Add testcases for GHCi multiple home units
Adds the following testcases:
* Evaluate code with a single home unit using 'initMulti' initialisation
logic
* More complicated testcase with multiple home units, testing reload
logic and code evaluation.
- - - - -
0a8781a6 by fendor at 2025-05-02T11:17:09+02:00
Make GHCi commands compatible with multiple home units
FIXME: proper commit message
- - - - -
2df3c795 by fendor at 2025-05-02T14:46:58+02:00
FIXME: this test case can be fixed by exploiting internals
- - - - -
73 changed files:
- compiler/GHC.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Rename/Unbound.hs
- compiler/GHC/Runtime/Context.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/StgToJS/Linker/Linker.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Types/Name/Ppr.hs
- compiler/GHC/Unit/Env.hs
- compiler/GHC/Unit/Home/Graph.hs
- compiler/GHC/Unit/Types.hs
- ghc/GHCi/UI.hs
- ghc/GHCi/UI/Info.hs
- ghc/GHCi/UI/Monad.hs
- ghc/Main.hs
- testsuite/driver/testlib.py
- testsuite/tests/backpack/cabal/bkpcabal08/bkpcabal08.stdout
- testsuite/tests/driver/T8526/T8526.stdout
- testsuite/tests/driver/fat-iface/fat014.stdout
- testsuite/tests/driver/multipleHomeUnits/multiGHCi.stderr
- testsuite/tests/ghc-api/T6145.hs
- testsuite/tests/ghc-api/annotations-literals/literals.hs
- testsuite/tests/ghc-api/annotations-literals/parsed.hs
- testsuite/tests/ghc-api/apirecomp001/myghc.hs
- testsuite/tests/ghc-api/fixed-nodes/T1.hs
- + testsuite/tests/ghci.debugger/scripts/break031/Makefile
- + testsuite/tests/ghci.debugger/scripts/break031/a/A.hs
- + testsuite/tests/ghci.debugger/scripts/break031/all.T
- + testsuite/tests/ghci.debugger/scripts/break031/b/B.hs
- + testsuite/tests/ghci.debugger/scripts/break031/break031a.script
- + testsuite/tests/ghci.debugger/scripts/break031/break031a.stdout
- + testsuite/tests/ghci.debugger/scripts/break031/break031b.script
- + testsuite/tests/ghci.debugger/scripts/break031/break031b.stderr
- + testsuite/tests/ghci.debugger/scripts/break031/break031b.stdout
- + testsuite/tests/ghci.debugger/scripts/break031/unitA
- + testsuite/tests/ghci.debugger/scripts/break031/unitB
- testsuite/tests/ghci/linking/dyn/T3372.hs
- + testsuite/tests/ghci/prog-mhu001/Makefile
- + testsuite/tests/ghci/prog-mhu001/e/E.hs
- + testsuite/tests/ghci/prog-mhu001/prog-mhu001.T
- + testsuite/tests/ghci/prog-mhu001/prog-mhu001.script
- + testsuite/tests/ghci/prog-mhu001/prog-mhu001.stdout
- + testsuite/tests/ghci/prog-mhu001/unitE
- + testsuite/tests/ghci/prog-mhu002/Makefile
- + testsuite/tests/ghci/prog-mhu002/a/A.hs
- + testsuite/tests/ghci/prog-mhu002/b/B.hs
- + testsuite/tests/ghci/prog-mhu002/c/C.hs
- + testsuite/tests/ghci/prog-mhu002/d/Main.hs
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.T
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.script
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.stderr
- + testsuite/tests/ghci/prog-mhu002/prog-mhu002.stdout
- + testsuite/tests/ghci/prog-mhu002/unitA
- + testsuite/tests/ghci/prog-mhu002/unitB
- + testsuite/tests/ghci/prog-mhu002/unitC
- + testsuite/tests/ghci/prog-mhu002/unitD
- testsuite/tests/ghci/prog018/prog018.stdout
- testsuite/tests/ghci/scripts/T13869.stdout
- testsuite/tests/ghci/scripts/T13997.stdout
- testsuite/tests/ghci/scripts/T17669.stdout
- testsuite/tests/ghci/scripts/T18330.stdout
- testsuite/tests/ghci/scripts/T1914.stdout
- testsuite/tests/ghci/scripts/T20217.stdout
- testsuite/tests/ghci/scripts/T20587.stdout
- testsuite/tests/ghci/scripts/T21110.stderr
- testsuite/tests/ghci/scripts/T6105.stdout
- testsuite/tests/ghci/scripts/T8042.stdout
- testsuite/tests/ghci/scripts/T8042recomp.stdout
- testsuite/tests/ghci/scripts/ghci024.stdout
- testsuite/tests/ghci/scripts/ghci058.script
- testsuite/tests/ghci/should_run/TopEnvIface.stdout
- testsuite/tests/quasiquotation/T7918.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/641ecf7b709f3f85a410821739ffea…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/641ecf7b709f3f85a410821739ffea…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/az/ghc-cpp] 119 commits: Fix infelicities in the Specialiser
by Alan Zimmerman (@alanz) 01 May '25
by Alan Zimmerman (@alanz) 01 May '25
01 May '25
Alan Zimmerman pushed to branch wip/az/ghc-cpp at Glasgow Haskell Compiler / GHC
Commits:
ce616f49 by Simon Peyton Jones at 2025-04-27T21:10:25+01:00
Fix infelicities in the Specialiser
On the way to #23109 (unary classes) I discovered some infelicities
(or maybe tiny bugs, I forget) in the type-class specialiser.
I also tripped over #25965, an outright bug in the rule matcher
Specifically:
* Refactor: I enhanced `wantCallsFor`, whih previously always said
`True`, to discard calls of class-ops, data constructors etc. This is
a bit more efficient; and it means we don't need to worry about
filtering them out later.
* Fix: I tidied up some tricky logic that eliminated redundant
specialisations. It wasn't working correctly. See the expanded
Note [Specialisations already covered], and
(MP3) in Note [Specialising polymorphic dictionaries].
See also the new top-level `alreadyCovered`
function, which now goes via `GHC.Core.Rules.ruleLhsIsMoreSpecific`
I also added a useful Note [The (CI-KEY) invariant]
* Fix #25965: fixed a tricky bug in the `go_fam_fam` in
`GHC.Core.Unify.uVarOrFam`, which allows matching to succeed
without binding all type varibles.
I enhanced Note [Apartness and type families] some more
* #25703. This ticket "just works" with -fpolymorphic-specialisation;
but I was surprised that it worked! In this MR I added documentation
to Note [Interesting dictionary arguments] to explain; and tests to
ensure it stays fixed.
- - - - -
22d11fa8 by Simon Peyton Jones at 2025-04-28T18:05:19-04:00
Track rewriter sets more accurately in constraint solving
The key change, which fixed #25440, is to call `recordRewriter` in
GHC.Tc.Solver.Rewrite.rewrite_exact_fam_app. This missing call meant
that we were secretly rewriting a Wanted with a Wanted, but not really
noticing; and that led to a very bad error message, as you can see
in the ticket.
But of course that led me into rabbit hole of other refactoring around
the RewriteSet code:
* Improve Notes [Wanteds rewrite Wanteds]
* Zonk the RewriterSet in `zonkCtEvidence` rather than only in GHC.Tc.Errors.
This is tidier anyway (e.g. de-clutters debug output), and helps with the
next point.
* In GHC.Tc.Solver.Equality.inertsCanDischarge, don't replace a constraint
with no rewriters with an equal constraint that has many. See
See (CE4) in Note [Combining equalities]
* Move zonkRewriterSet and friends from GHC.Tc.Zonk.Type into
GHC.Tc.Zonk.TcType, where they properly belong.
A handful of tests get better error messages.
For some reason T24984 gets 12% less compiler allocation -- good
Metric Decrease:
T24984
- - - - -
6467d61e by Brandon Chinn at 2025-04-29T18:36:03-04:00
Fix lexing "\^\" (#25937)
This broke in the refactor in !13128, where the old code parsed escape
codes and collapsed string gaps at the same time, but the new code
collapsed gaps first, then resolved escape codes. The new code used a
naive heuristic to skip escaped backslashes, but didn't account for
"\^\".
- - - - -
99868a86 by Jens Petersen at 2025-04-29T18:36:44-04:00
hadrian: default selftest to disabled
- - - - -
aba2a4a5 by Zubin Duggal at 2025-04-30T06:35:59-04:00
get-win32-tarballs.py: List tarball files to be downloaded if we cannot find them
Fixes #25929
- - - - -
d99a617b by Ben Gamari at 2025-04-30T06:36:40-04:00
Move Data ModuleName instance to Language.Haskell.Syntax.Module.Name
Fixes #25968.
- - - - -
b5e557d8 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
GHC-CPP: first rough proof of concept
Processes
#define FOO
#ifdef FOO
x = 1
#endif
Into
[ITcppIgnored [L loc ITcppDefine]
,ITcppIgnored [L loc ITcppIfdef]
,ITvarid "x"
,ITequal
,ITinteger (IL {il_text = SourceText "1", il_neg = False, il_value = 1})
,ITcppIgnored [L loc ITcppEndif]
,ITeof]
In time, ITcppIgnored will be pushed into a comment
- - - - -
8571387c by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Tidy up before re-visiting the continuation mechanic
- - - - -
92273c0f by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Switch preprocessor to continuation passing style
Proof of concept, needs tidying up
- - - - -
d8c87361 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Small cleanup
- - - - -
30a1a4e5 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Get rid of some cruft
- - - - -
7dd5d77c by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Starting to integrate.
Need to get the pragma recognised and set
- - - - -
b44b17cf by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Make cppTokens extend to end of line, and process CPP comments
- - - - -
71d19727 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Remove unused ITcppDefined
- - - - -
c326a944 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Allow spaces between # and keyword for preprocessor directive
- - - - -
9dcd821c by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Process CPP continuation lines
They are emited as separate ITcppContinue tokens.
Perhaps the processing should be more like a comment, and keep on
going to the end.
BUT, the last line needs to be slurped as a whole.
- - - - -
873d3c9b by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Accumulate CPP continuations, process when ready
Can be simplified further, we only need one CPP token
- - - - -
1d604a35 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Simplify Lexer interface. Only ITcpp
We transfer directive lines through it, then parse them from scratch
in the preprocessor.
- - - - -
bcd77e8b by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Deal with directive on last line, with no trailing \n
- - - - -
55f1056a by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Start parsing and processing the directives
- - - - -
8f2079a7 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Prepare for processing include files
- - - - -
2407cbed by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Move PpState into PreProcess
And initParserState, initPragState too
- - - - -
8a9008c4 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Process nested include files
Also move PpState out of Lexer.x, so it is easy to evolve it in a ghci
session, loading utils/check-cpp/Main.hs
- - - - -
24e47f5d by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Split into separate files
- - - - -
ace37ecb by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Starting on expression parser.
But it hangs. Time for Text.Parsec.Expr
- - - - -
d7c05912 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Start integrating the ghc-cpp work
From https://github.com/alanz/ghc-cpp
- - - - -
c96e142b by Alan Zimmerman at 2025-04-30T18:27:18+01:00
WIP
- - - - -
c4cc4cec by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Fixup after rebase
- - - - -
1728a5f9 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
WIP
- - - - -
86eb1e35 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Fixup after rebase, including all tests pass
- - - - -
091892a4 by Alan Zimmerman at 2025-04-30T18:27:18+01:00
Change pragma usage to GHC_CPP from GhcCPP
- - - - -
fc6e9524 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Some comments
- - - - -
7e907713 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Reformat
- - - - -
9844268f by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Delete unused file
- - - - -
714dec3b by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Rename module Parse to ParsePP
- - - - -
6c09c72a by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Clarify naming in the parser
- - - - -
90f621b0 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
WIP. Switching to alex/happy to be able to work in-tree
Since Parsec is not available
- - - - -
cdc19c1d by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Layering is now correct
- GHC lexer, emits CPP tokens
- accumulated in Preprocessor state
- Lexed by CPP lexer, CPP command extracted, tokens concated with
spaces (to get rid of token pasting via comments)
- if directive lexed and parsed by CPP lexer/parser, and evaluated
- - - - -
5a95ab9e by Alan Zimmerman at 2025-04-30T18:27:19+01:00
First example working
Loading Example1.hs into ghci, getting the right results
```
{-# LANGUAGE GHC_CPP #-}
module Example1 where
y = 3
x =
"hello"
"bye now"
foo = putStrLn x
```
- - - - -
62a44662 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Rebase, and all tests pass except whitespace for generated parser
- - - - -
e390dc29 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
More plumbing. Ready for testing tomorrow.
- - - - -
a854d7d1 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Proress. Renamed module State from Types
And at first blush it seems to handle preprocessor scopes properly.
- - - - -
8413c8a1 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Insert basic GHC version macros into parser
__GLASGOW_HASKELL__
__GLASGOW_HASKELL_FULL_VERSION__
__GLASGOW_HASKELL_PATCHLEVEL1__
__GLASGOW_HASKELL_PATCHLEVEL2__
- - - - -
2b2b9228 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Re-sync check-cpp for easy ghci work
- - - - -
430277cc by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Get rid of warnings
- - - - -
56c60aa3 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Rework macro processing, in check-cpp
Macros kept at the top level, looked up via name, multiple arity
versions per name can be stored
- - - - -
ed637dcd by Alan Zimmerman at 2025-04-30T18:27:19+01:00
WIP. Can crack arguments for #define
Next step it to crack out args in an expansion
- - - - -
eb140d03 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
WIP on arg parsing.
- - - - -
c93e5c43 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Progress. Still screwing up nested parens.
- - - - -
b01ee9be by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Seems to work, but has redundant code
- - - - -
57e61eb2 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Remove redundant code
- - - - -
53a013e9 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Reformat
- - - - -
ff5d845d by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Expand args, single pass
Still need to repeat until fixpoint
- - - - -
eabfa64f by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Fixed point expansion
- - - - -
76e3c95c by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Sync the playground to compiler
- - - - -
b308b101 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Working on dumping the GHC_CPP result
But We need to keep the BufSpan in a comment
- - - - -
8216dfd9 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Keep BufSpan in queued comments in GHC.Parser.Lexer
- - - - -
4aa75569 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Getting close to being able to print the combined tokens
showing what is in and what is out
- - - - -
621fd6bc by Alan Zimmerman at 2025-04-30T18:27:19+01:00
First implementation of dumpGhcCpp.
Example output
First dumps all macros in the state, then the source, showing which
lines are in and which are out
------------------------------
- |#define FOO(A,B) A + B
- |#define FOO(A,B,C) A + B + C
- |#if FOO(1,FOO(3,4)) == 8
- |-- a comment
|x = 1
- |#else
- |x = 5
- |#endif
- - - - -
38b978bc by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Clean up a bit
- - - - -
5b80b455 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Add -ddump-ghc-cpp option and a test based on it
- - - - -
fddd2454 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Restore Lexer.x rules, we need them for continuation lines
- - - - -
30b3055a by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Lexer.x: trying to sort out the span for continuations
- We need to match on \n at the end of the line
- We cannot simply back up for it
- - - - -
fc8d7dc7 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Inserts predefined macros. But does not dump properly
Because the cpp tokens have a trailing newline
- - - - -
b12d9528 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Remove unnecessary LExer rules
We *need* the ones that explicitly match to the end of the line.
- - - - -
95da0848 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Generate correct span for ITcpp
Dump now works, except we do not render trailing `\` for continuation
lines. This is good enough for use in test output.
- - - - -
a89c12e4 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Reduce duplication in lexer
- - - - -
c072ea30 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Tweaks
- - - - -
ff1e169e by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Insert min_version predefined macros into state
The mechanism now works. Still need to flesh out the full set.
- - - - -
77b2fb0b by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Trying my alternative pragma syntax.
It works, but dumpGhcCpp is broken, I suspect from the ITcpp token
span update.
- - - - -
946fcffe by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Pragma extraction now works, with both CPP and GHC_CPP
For the following
{-# LANGUAGE CPP #-}
#if __GLASGOW_HASKELL__ >= 913
{-# LANGUAGE GHC_CPP #-}
#endif
We will enable GHC_CPP only
- - - - -
ea220ec5 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Remove some tracing
- - - - -
77e29d38 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Fix test exes for changes
- - - - -
a05c2b54 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
For GHC_CPP tests, normalise config-time-based macros
- - - - -
b872a140 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
WIP
- - - - -
171744b2 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
WIP again. What is wrong?
- - - - -
66b3d2b5 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Revert to dynflags for normal not pragma lexing
- - - - -
7c9b44a3 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Working on getting check-exact to work properly
- - - - -
614ea6a0 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Passes CppCommentPlacement test
- - - - -
eb13851f by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Starting on exact printing with GHC_CPP
While overriding normal CPP
- - - - -
25842766 by Alan Zimmerman at 2025-04-30T18:27:19+01:00
Correctly store CPP ignored tokens as comments
By populating the lexeme string in it, based on the bufpos
- - - - -
c7c62d60 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
WIP
- - - - -
950201a7 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Simplifying
- - - - -
71e2e916 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Update the active state logic
- - - - -
1f85f1fd by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Work the new logic into the mainline code
- - - - -
44385d18 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Process `defined` operator
- - - - -
bd22d304 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Manage lexer state while skipping tokens
There is very intricate layout-related state used when lexing. If a
CPP directive blanks out some tokens, store this state when the
blanking starts, and restore it when they are no longer being blanked.
- - - - -
e967f92b by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Track the last token buffer index, for ITCppIgnored
We need to attach the source being skipped in an ITCppIgnored token.
We cannot simply use its BufSpan as an index into the underlying
StringBuffer as it counts unicode chars, not bytes.
So we update the lexer state to store the starting StringBuffer
location for the last token, and use the already-stored length to
extract the correct portion of the StringBuffer being parsed.
- - - - -
69b1c666 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Process the ! operator in GHC_CPP expressions
- - - - -
589bf9fb by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Predefine a constant when GHC_CPP is being used.
- - - - -
e5080cfb by Alan Zimmerman at 2025-04-30T18:27:20+01:00
WIP
- - - - -
46b58f7c by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Skip lines directly in the lexer when required
- - - - -
51db8d2f by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Properly manage location when accepting tokens again
- - - - -
f7851788 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Seems to be working now, for Example9
- - - - -
23ca6470 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Remove tracing
- - - - -
b5c3c800 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Fix parsing '*' in block comments
Instead of replacing them with '-'
- - - - -
34952423 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Keep the trailing backslash in a ITcpp token
- - - - -
967699fe by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Deal with only enabling one section of a group.
A group is an instance of a conditional introduced by
#if/#ifdef/#ifndef,
and ending at the final #endif, including intermediate #elsif sections
- - - - -
7496a89d by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Replace remaining identifiers with 0 when evaluating
As per the spec
- - - - -
7d8ae8e0 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Snapshot before rebase
- - - - -
cbaef129 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Skip non-processed lines starting with #
- - - - -
dbbf4975 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Export generateMacros so we can use it in ghc-exactprint
- - - - -
89e62cfd by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Fix rebase
- - - - -
922d6f93 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Expose initParserStateWithMacrosString
- - - - -
0591e754 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Fix buggy lexer cppSkip
It was skipping all lines, not just ones prefixed by #
- - - - -
d1437795 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Fix evaluation of && to use the correct operator
- - - - -
6f1b578d by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Deal with closing #-} at the start of a line
- - - - -
b323cddc by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Add the MIN_VERSION_GLASGOW_HASKELL predefined macro
- - - - -
a95937c9 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Include MIN_VERSION_GLASGOW_HASKELL in GhcCpp01.stderr
- - - - -
8d808fb3 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Use a strict map for macro defines
- - - - -
7b305c1f by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Process TIdentifierLParen
Which only matters at the start of #define
- - - - -
93e98895 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Do not provide TIdentifierLParen paren twice
- - - - -
6c1cc903 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Handle whitespace between identifier and '(' for directive only
- - - - -
f6bc6402 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Expose some Lexer bitmap manipulation helpers
- - - - -
9c0c7d3a by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Deal with line pragmas as tokens
Blows up for dumpGhcCpp though
- - - - -
91877c57 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Allow strings delimited by a single quote too
- - - - -
a35d6cc1 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Allow leading whitespace on cpp directives
As per https://timsong-cpp.github.io/cppwp/n4140/cpp#1
- - - - -
e271da2f by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Implement GHC_CPP undef
- - - - -
da493772 by Alan Zimmerman at 2025-04-30T18:27:20+01:00
Sort out expansion of no-arg macros, in a context with args
And make the expansion bottom out, in the case of recursion
- - - - -
115 changed files:
- compiler/GHC.hs
- compiler/GHC/Cmm/Lexer.x
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/Cmm/Parser/Monad.hs
- compiler/GHC/Core/Coercion.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Parser.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Parser.hs-boot
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/HaddockLex.x
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Parser/Lexer.x
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- + compiler/GHC/Parser/PreProcess.hs
- + compiler/GHC/Parser/PreProcess/Eval.hs
- + compiler/GHC/Parser/PreProcess/Lexer.x
- + compiler/GHC/Parser/PreProcess/Macro.hs
- + compiler/GHC/Parser/PreProcess/ParsePP.hs
- + compiler/GHC/Parser/PreProcess/Parser.y
- + compiler/GHC/Parser/PreProcess/ParserM.hs
- + compiler/GHC/Parser/PreProcess/State.hs
- compiler/GHC/Parser/String.hs
- compiler/GHC/Parser/Utils.hs
- compiler/GHC/SysTools/Cpp.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Unit/Types.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- compiler/ghc.cabal.in
- docs/users_guide/debugging.rst
- ghc/GHCi/UI.hs
- hadrian/README.md
- hadrian/hadrian.cabal
- hadrian/src/Rules/SourceDist.hs
- hadrian/stack.yaml.lock
- libraries/ghc-internal/src/GHC/Internal/LanguageExtensions.hs
- m4/fp_setup_windows_toolchain.m4
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/driver/T4437.hs
- testsuite/tests/ghc-api/T11579.hs
- + testsuite/tests/ghc-cpp/GhcCpp01.hs
- + testsuite/tests/ghc-cpp/GhcCpp01.stderr
- + testsuite/tests/ghc-cpp/all.T
- testsuite/tests/indexed-types/should_fail/T3330c.stderr
- testsuite/tests/indexed-types/should_fail/T4174.stderr
- testsuite/tests/indexed-types/should_fail/T8227.stderr
- testsuite/tests/interface-stability/template-haskell-exports.stdout
- + testsuite/tests/parser/should_run/T25937.hs
- + testsuite/tests/parser/should_run/T25937.stdout
- testsuite/tests/parser/should_run/all.T
- + testsuite/tests/parser/should_run/parser_unit_tests.hs
- + testsuite/tests/printer/CppCommentPlacement.hs
- + testsuite/tests/simplCore/should_compile/T25703.hs
- + testsuite/tests/simplCore/should_compile/T25703.stderr
- + testsuite/tests/simplCore/should_compile/T25703a.hs
- + testsuite/tests/simplCore/should_compile/T25703a.stderr
- + testsuite/tests/simplCore/should_compile/T25965.hs
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/typecheck/should_compile/T25266a.stderr
- testsuite/tests/typecheck/should_fail/T18851.stderr
- + utils/check-cpp/.ghci
- + utils/check-cpp/.gitignore
- + utils/check-cpp/Eval.hs
- + utils/check-cpp/Example1.hs
- + utils/check-cpp/Example10.hs
- + utils/check-cpp/Example11.hs
- + utils/check-cpp/Example12.hs
- + utils/check-cpp/Example13.hs
- + utils/check-cpp/Example2.hs
- + utils/check-cpp/Example3.hs
- + utils/check-cpp/Example4.hs
- + utils/check-cpp/Example5.hs
- + utils/check-cpp/Example6.hs
- + utils/check-cpp/Example7.hs
- + utils/check-cpp/Example8.hs
- + utils/check-cpp/Example9.hs
- + utils/check-cpp/Lexer.x
- + utils/check-cpp/Macro.hs
- + utils/check-cpp/Main.hs
- + utils/check-cpp/ParsePP.hs
- + utils/check-cpp/ParseSimulate.hs
- + utils/check-cpp/Parser.y
- + utils/check-cpp/ParserM.hs
- + utils/check-cpp/PreProcess.hs
- + utils/check-cpp/README.md
- + utils/check-cpp/State.hs
- + utils/check-cpp/run.sh
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Preprocess.hs
- utils/check-exact/Utils.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hyperlinker/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Parser.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/186cff7e2725ff7e2c58fc62e5cbe8…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/186cff7e2725ff7e2c58fc62e5cbe8…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/T23109a] 10 commits: Fix lexing "\^\" (#25937)
by Simon Peyton Jones (@simonpj) 01 May '25
by Simon Peyton Jones (@simonpj) 01 May '25
01 May '25
Simon Peyton Jones pushed to branch wip/T23109a at Glasgow Haskell Compiler / GHC
Commits:
6467d61e by Brandon Chinn at 2025-04-29T18:36:03-04:00
Fix lexing "\^\" (#25937)
This broke in the refactor in !13128, where the old code parsed escape
codes and collapsed string gaps at the same time, but the new code
collapsed gaps first, then resolved escape codes. The new code used a
naive heuristic to skip escaped backslashes, but didn't account for
"\^\".
- - - - -
99868a86 by Jens Petersen at 2025-04-29T18:36:44-04:00
hadrian: default selftest to disabled
- - - - -
aba2a4a5 by Zubin Duggal at 2025-04-30T06:35:59-04:00
get-win32-tarballs.py: List tarball files to be downloaded if we cannot find them
Fixes #25929
- - - - -
d99a617b by Ben Gamari at 2025-04-30T06:36:40-04:00
Move Data ModuleName instance to Language.Haskell.Syntax.Module.Name
Fixes #25968.
- - - - -
c28c68ed by Simon Peyton Jones at 2025-05-01T16:04:46+01:00
Improve the Simplifier
While working on #23109, I made two improvements to the Simplifier
* I found that the Simplifier was sometimes iterating more than it should.
I fixed this by improving postInlineUnconditionally.
* I refactored tryCastWorkerWrapper. It is now clearer, and does less
repeated work. This allowed me to call it from makeTrivial, which again
does a bit more in one pass, elminating a potential extra Simplifier
iteration
More care in postInline
Don't inline data con apps so vigorously
needs more docs
Wibbles
Be more careful in mkDupableContWithDmds
to not create a binding that will immediately be inlined
Do post-inline used-once bindings
This makes cacheprof not regress and seems generally a good plan
More eperiments
* Don't inline toplevel things so much
* Don't float constants so vigorously in the first float-out
Comments only
Refator GHC.Core.Opt.SetLevels.notWorthFloating
I refactored `notWorthFloating` while I was doing something else.
I don't think there's a change in behaviour, but if so it's very much
a corner case.
Always float bottoming expressions to the top
...regardless of floatConsts
Comments only
Wibble SetLevels
Try getting rid of this early-phase business
Don't float PAPs to top level
...and treat case alternatives as strict contexts
Wibble to postInlineUnconditionally
Small wibbles
Don't make error calls interesting.
Literals say True too isSaturatedConApp
Import wibble
Tiny change to saves_alloc
Float lambdas (and PAPs) out of lambdas to top level
This improves spectral/cse
But the old comment was
-- is_con_app: don't float PAPs to the top; they may well end
-- up getting eta-expanded and re-inlined
-- E.g. f = \x -> (++) ys
-- If we float, then eta-expand we get
-- lvl = (++) ys
-- f = \x \zs -> lvl zs
-- and now we'll inline lvl. Silly.
Let's see what CI says
- - - - -
48a86d23 by Simon Peyton Jones at 2025-05-01T16:04:46+01:00
Specialise the (higher order) showSignedFloat
- - - - -
6ac35704 by Simon Peyton Jones at 2025-05-01T16:04:46+01:00
Eta reduce augment and its rules
... to match foldr. I found this reduced some simplifer iterations
Fix `augment`!
- - - - -
d76c1929 by Simon Peyton Jones at 2025-05-01T16:04:46+01:00
Subtle change to OccurAnal
See (JP2) in Note [Occurrence analysis for join points]
- - - - -
fed7616e by Simon Peyton Jones at 2025-05-01T16:04:46+01:00
Accept some error message changes
* break011, break024: GHCi debugger output. Not quite so good but
@alt-romes says it's fine. Very delicate tests, depend on fluky
inlining.
* inline-check: an improvement! After this patch we do one fewer
iterations of the Simplifier.
- - - - -
fbdf66f1 by Simon Peyton Jones at 2025-05-01T16:04:46+01:00
Accept diff
* T18793: good: code is simpler and better
- - - - -
26 changed files:
- compiler/GHC/Core/Opt/Exitify.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/Parser/Errors/Types.hs
- compiler/GHC/Parser/String.hs
- compiler/GHC/Unit/Types.hs
- compiler/Language/Haskell/Syntax/Module/Name.hs
- hadrian/README.md
- hadrian/hadrian.cabal
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Float.hs
- m4/fp_setup_windows_toolchain.m4
- testsuite/tests/arityanal/should_compile/T18793.stderr
- testsuite/tests/driver/inline-check.stderr
- testsuite/tests/ghci.debugger/scripts/break011.stdout
- testsuite/tests/ghci.debugger/scripts/break024.stdout
- + testsuite/tests/parser/should_run/T25937.hs
- + testsuite/tests/parser/should_run/T25937.stdout
- testsuite/tests/parser/should_run/all.T
- + testsuite/tests/parser/should_run/parser_unit_tests.hs
- testsuite/tests/simplCore/should_run/simplrun009.hs
Changes:
=====================================
compiler/GHC/Core/Opt/Exitify.hs
=====================================
@@ -1,9 +1,7 @@
module GHC.Core.Opt.Exitify ( exitifyProgram ) where
-{-
-Note [Exitification]
-~~~~~~~~~~~~~~~~~~~~
-
+{- Note [Exitification]
+~~~~~~~~~~~~~~~~~~~~~~~
This module implements Exitification. The goal is to pull as much code out of
recursive functions as possible, as the simplifier is better at inlining into
call-sites that are not in recursive functions.
@@ -33,6 +31,9 @@ Example result:
in …
Now `t` is no longer in a recursive function, and good things happen!
+
+There is also a tricky connectionn with occurrence analysis:
+see (JP2) in Note [Occurrence analysis for join points] in GHC.Core.Opt.OccurAnal.
-}
import GHC.Prelude
=====================================
compiler/GHC/Core/Opt/OccurAnal.hs
=====================================
@@ -55,7 +55,7 @@ import GHC.Types.Tickish
import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Types.Var
-import GHC.Types.Demand ( argOneShots, argsOneShots, isDeadEndSig )
+import GHC.Types.Demand ( argOneShots, argsOneShots {- , isDeadEndSig -} )
import GHC.Utils.Outputable
import GHC.Utils.Panic
@@ -619,7 +619,7 @@ notice that `v` occurs at most once in any case branch; the occurrence analyser
spots this and returns a OneOcc{ occ_n_br = 3 } for `v`. Then the code in
GHC.Core.Opt.Simplify.Utils.postInlineUnconditionally inlines `v` at its three
use sites, and discards the let-binding. That way, we avoid allocating `v` in
-the A,B,C branches (though we still compute it of course), and branch D
+*the A,B,C branches (though we still compute it of course), and branch D
doesn't involve <small thunk> at all. This sometimes makes a Really Big
Difference.
@@ -687,9 +687,39 @@ Here are the consequences
These are `andUDs` together in `addOccInfo`, and hence
`v` gets ManyOccs, just as it should. Clever!
-There are a couple of tricky wrinkles
+There are some tricky wrinkles
-(W1) Consider this example which shadows `j`:
+(JP1) What if the join point binding has a stable unfolding, or RULES?
+ They are just alternative right-hand sides, and at each call site we
+ will use only one of them. So again, we can use `orUDs` to combine
+ usage info from all these alternatives RHSs.
+
+(JP2) Consider this (test T21128):
+ joinrec jr x ys = case ys of
+ [] -> v+1
+ (x:xs) -> jr x xs
+ The exitification pass will carefully float out the exit path, thus:
+ join j x = v + 1 in
+ joinrec jr x ys = case ys of
+ [] -> j x
+ (x:xs) -> jr x xs
+ The idea is that now `v` may occur once, not under a lambda, and so may
+ be inlined. See Note [Exitification] in GHC.Core.Opt.Exitify.
+
+ BUT if we "virtually inline" `j` at its occurrence side in `jr`, it'll
+ look as if `v` occurs under a lambda. Boo! That defeats the entire
+ purpose of exitification!
+
+ Fortunately it is easy to fix. In `lookupOccInfo` we can see if `n_br=0`.
+ If so, all the ocurrences of this Id came from non-recursive join points
+ (via the mechanism above) and so can't be involved in a loop. So we do
+ not need to mark them as IsInsideLam.
+
+ This is a pretty subtle point!
+
+There are some other wrinkles to do with shadowing:
+
+(SW1) Consider this example which shadows `j`:
join j = rhs in
in case x of { K j -> ..j..; ... }
Clearly when we come to the pattern `K j` we must drop the `j`
@@ -697,7 +727,7 @@ There are a couple of tricky wrinkles
This is done by `drop_shadowed_joins` in `addInScope`.
-(W2) Consider this example which shadows `v`:
+(SW2) Consider this example which shadows `v`:
join j = ...v...
in case x of { K v -> ..j..; ... }
@@ -717,13 +747,13 @@ There are a couple of tricky wrinkles
* In `postprcess_uds`, we add the chucked-out join points to the
returned UsageDetails, with `andUDs`.
-(W3) Consider this example, which shadows `j`, but this time in an argument
+(SW3) Consider this example, which shadows `j`, but this time in an argument
join j = rhs
in f (case x of { K j -> ...; ... })
We can zap the entire occ_join_points when looking at the argument,
because `j` can't posibly occur -- it's a join point! And the smaller
occ_join_points is, the better. Smaller to look up in mkOneOcc, and
- more important, less looking-up when checking (W2).
+ more important, less looking-up when checking (SW2).
This is done in setNonTailCtxt. It's important /not/ to do this for
join-point RHS's because of course `j` can occur there!
@@ -731,12 +761,7 @@ There are a couple of tricky wrinkles
NB: this is just about efficiency: it is always safe /not/ to zap the
occ_join_points.
-(W4) What if the join point binding has a stable unfolding, or RULES?
- They are just alternative right-hand sides, and at each call site we
- will use only one of them. So again, we can use `orUDs` to combine
- usage info from all these alternatives RHSs.
-
-Wrinkles (W1) and (W2) are very similar to Note [Binder swap] (BS3).
+Wrinkles (SW1) and (SW2) are very similar to Note [Binder swap] (BS3).
Note [Finding join points]
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -985,7 +1010,7 @@ occAnalBind !env lvl ire (NonRec bndr rhs) thing_inside combine
= -- Analyse the RHS and /then/ the body
let -- Analyse the rhs first, generating rhs_uds
!(rhs_uds_s, bndr', rhs') = occAnalNonRecRhs env lvl ire mb_join bndr rhs
- rhs_uds = foldr1 orUDs rhs_uds_s -- NB: orUDs. See (W4) of
+ rhs_uds = foldr1 orUDs rhs_uds_s -- NB: orUDs. See (JP1) of
-- Note [Occurrence analysis for join points]
-- Now analyse the body, adding the join point
@@ -1096,14 +1121,14 @@ mkNonRecRhsCtxt lvl bndr unf
certainly_inline -- See Note [Cascading inlines]
= -- mkNonRecRhsCtxt is only used for non-join points, so occAnalBind
-- has set the OccInfo for this binder before calling occAnalNonRecRhs
+ -- Distressing delicacy ... has to line up with preInlineUnconditionally
case idOccInfo bndr of
OneOcc { occ_in_lam = NotInsideLam, occ_n_br = 1 }
- -> active && not stable_unf && not top_bottoming
+ -> active && not (isTopLevel lvl) && not stable_unf
_ -> False
active = isAlwaysActive (idInlineActivation bndr)
stable_unf = isStableUnfolding unf
- top_bottoming = isTopLevel lvl && isDeadEndId bndr
-----------------
occAnalRecBind :: OccEnv -> TopLevelFlag -> ImpRuleEdges -> [(Var,CoreExpr)]
@@ -2580,8 +2605,9 @@ occAnalArgs !env fun args !one_shots
-- Make bottoming functions interesting
-- See Note [Bottoming function calls]
- encl | Var f <- fun, isDeadEndSig (idDmdSig f) = OccScrut
- | otherwise = OccVanilla
+-- encl | Var f <- fun, isDeadEndSig (idDmdSig f) = OccScrut
+-- | otherwise = OccVanilla
+ encl = OccVanilla
go uds fun [] _ = WUD uds fun
go uds fun (arg:args) one_shots
@@ -2606,7 +2632,8 @@ Consider
let x = (a,b) in
case p of
A -> ...(error x)..
- B -> ...(ertor x)...
+ B -> ...(error x)...
+ C -> ..blah...
postInlineUnconditionally may duplicate x's binding, but sometimes it
does so only if the use site IsInteresting. Pushing allocation into error
@@ -2616,6 +2643,9 @@ setting occ_encl = OccScrut for such calls.
The slightly-artificial test T21128 is a good example. It's probably
not a huge deal.
+ToDo!!! Fix comment. Now postinlineUnconditionally ignores intersting-ness for
+non-top-level things.
+
Note [Arguments of let-bound constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
@@ -2979,7 +3009,7 @@ mkRhsOccEnv env@(OccEnv { occ_one_shots = ctxt_one_shots, occ_join_points = ctxt
zapJoinPointInfo :: JoinPointInfo -> JoinPointInfo
-- (zapJoinPointInfo jp_info) basically just returns emptyVarEnv (hence zapped).
--- See (W3) of Note [Occurrence analysis for join points]
+-- See (SW3) of Note [Occurrence analysis for join points]
--
-- Zapping improves efficiency, slightly, if you accidentally introduce a bug,
-- in which you zap [jx :-> uds] and then find an occurrence of jx anyway, you
@@ -3086,7 +3116,7 @@ preprocess_env env@(OccEnv { occ_join_points = join_points
= env { occ_bs_env = swap_env `minusUFM` bndr_fm }
drop_shadowed_joins :: OccEnv -> OccEnv
- -- See Note [Occurrence analysis for join points] wrinkle2 (W1) and (W2)
+ -- See Note [Occurrence analysis for join points] wrinkles (SW1) and (SW2)
drop_shadowed_joins env = env { occ_join_points = emptyVarEnv }
-- bad_joins is true if it would be wrong to push occ_join_points inwards
@@ -3111,7 +3141,7 @@ postprocess_uds bndrs bad_joins uds
add_bad_joins :: UsageDetails -> UsageDetails
-- Add usage info for occ_join_points that we cannot push inwards
-- because of shadowing
- -- See Note [Occurrence analysis for join points] wrinkle (W2)
+ -- See Note [Occurrence analysis for join points] wrinkle (SW2)
add_bad_joins uds
| isEmptyVarEnv bad_joins = uds
| otherwise = modifyUDEnv extend_with_bad_joins uds
@@ -3792,8 +3822,11 @@ lookupOccInfoByUnique (UD { ud_env = env
, occ_int_cxt = int_cxt
, occ_tail = mk_tail_info tail_info }
where
- in_lam | uniq `elemVarEnvByKey` z_in_lam = IsInsideLam
- | otherwise = NotInsideLam
+ in_lam | uniq `elemVarEnvByKey` z_in_lam
+ , n_br > 0 -- n_br>0: see (JP2) in
+ = IsInsideLam -- Note [Occurrence analysis for join points]
+ | otherwise
+ = NotInsideLam
Just (ManyOccL tail_info) -> ManyOccs { occ_tail = mk_tail_info tail_info }
where
@@ -3801,8 +3834,6 @@ lookupOccInfoByUnique (UD { ud_env = env
| uniq `elemVarEnvByKey` z_tail = NoTailCallInfo
| otherwise = ti
-
-
-------------------
-- See Note [Adjusting right-hand sides]
=====================================
compiler/GHC/Core/Opt/Pipeline.hs
=====================================
@@ -217,7 +217,7 @@ getCoreToDo dflags hpt_rule_base extra_vars
if full_laziness then
CoreDoFloatOutwards $ FloatOutSwitches
{ floatOutLambdas = Just 0
- , floatOutConstants = True
+ , floatOutConstants = False -- Initially
, floatOutOverSatApps = False
, floatToTopLevelOnly = False
, floatJoinsToTop = False -- Initially, don't float join points at all
@@ -284,7 +284,7 @@ getCoreToDo dflags hpt_rule_base extra_vars
-- f_el22 (f_el21 r_midblock)
runWhen full_laziness $ CoreDoFloatOutwards $ FloatOutSwitches
{ floatOutLambdas = floatLamArgs dflags
- , floatOutConstants = True
+ , floatOutConstants = True -- For SpecConstr and CSE
, floatOutOverSatApps = True
, floatToTopLevelOnly = False
, floatJoinsToTop = True },
=====================================
compiler/GHC/Core/Opt/SetLevels.hs
=====================================
@@ -406,7 +406,7 @@ lvlApp env orig_expr ((_,AnnVar fn), args)
, arity < n_val_args
, Nothing <- isClassOpId_maybe fn
= do { rargs' <- mapM (lvlNonTailMFE env False) rargs
- ; lapp' <- lvlNonTailMFE env False lapp
+ ; lapp' <- lvlNonTailMFE env True lapp
; return (foldl' App lapp' rargs') }
| otherwise
@@ -482,14 +482,14 @@ Consider this:
f :: T Int -> blah
f x vs = case x of { MkT y ->
let f vs = ...(case y of I# w -> e)...f..
- in f vs
+ in f vs }
Here we can float the (case y ...) out, because y is sure
to be evaluated, to give
f x vs = case x of { MkT y ->
- case y of I# w ->
+ case y of { I# w ->
let f vs = ...(e)...f..
- in f vs
+ in f vs }}
That saves unboxing it every time round the loop. It's important in
some DPH stuff where we really want to avoid that repeated unboxing in
@@ -614,7 +614,8 @@ lvlMFE env strict_ctxt e@(_, AnnCase {})
= lvlExpr env e -- See Note [Case MFEs]
lvlMFE env strict_ctxt ann_expr
- | not float_me
+ | notWorthFloating expr abs_vars
+ || not float_me
|| floatTopLvlOnly env && not (isTopLvl dest_lvl)
-- Only floating to the top level is allowed.
|| hasFreeJoin env fvs -- If there is a free join, don't float
@@ -623,9 +624,6 @@ lvlMFE env strict_ctxt ann_expr
-- We can't let-bind an expression if we don't know
-- how it will be represented at runtime.
-- See Note [Representation polymorphism invariants] in GHC.Core
- || notWorthFloating expr abs_vars
- -- Test notWorhtFloating last;
- -- See Note [Large free-variable sets]
= -- Don't float it out
lvlExpr env ann_expr
@@ -676,12 +674,11 @@ lvlMFE env strict_ctxt ann_expr
is_function = isFunction ann_expr
mb_bot_str = exprBotStrictness_maybe expr
-- See Note [Bottoming floats]
- -- esp Bottoming floats (2)
+ -- esp Bottoming floats (BF2)
expr_ok_for_spec = exprOkForSpeculation expr
abs_vars = abstractVars dest_lvl env fvs
dest_lvl = destLevel env fvs fvs_ty is_function is_bot_lam
- -- NB: is_bot_lam not is_bot; see (3) in
- -- Note [Bottoming floats]
+ -- NB: is_bot_lam not is_bot; see (BF2) in Note [Bottoming floats]
-- float_is_new_lam: the floated thing will be a new value lambda
-- replacing, say (g (x+4)) by (lvl x). No work is saved, nor is
@@ -698,20 +695,32 @@ lvlMFE env strict_ctxt ann_expr
-- A decision to float entails let-binding this thing, and we only do
-- that if we'll escape a value lambda, or will go to the top level.
+ -- Never float trivial expressions;
+ -- notably, save_work might be true of a lone evaluated variable.
float_me = saves_work || saves_alloc || is_mk_static
-- See Note [Saving work]
- saves_work = escapes_value_lam -- (a)
- && not (exprIsHNF expr) -- (b)
- && not float_is_new_lam -- (c)
+ is_hnf = exprIsHNF expr
+ saves_work = escapes_value_lam -- (SW-a)
+ && not is_hnf -- (SW-b)
+ && not float_is_new_lam -- (SW-c)
escapes_value_lam = dest_lvl `ltMajLvl` (le_ctxt_lvl env)
- -- See Note [Saving allocation] and Note [Floating to the top]
- saves_alloc = isTopLvl dest_lvl
- && floatConsts env
- && ( not strict_ctxt -- (a)
- || exprIsHNF expr -- (b)
- || (is_bot_lam && escapes_value_lam)) -- (c)
+ -- See Note [Floating to the top]
+-- is_con_app = isSaturatedConApp expr -- True of literal strings too
+ saves_alloc = isTopLvl dest_lvl
+ && (escapes_value_lam || floatConsts env)
+ -- Always float allocation out of a value lambda
+ -- if it gets to top level
+ && (not strict_ctxt || is_hnf || is_bot_lam)
+ -- is_con_app: don't float PAPs to the top; they may well end
+ -- up getting eta-expanded and re-inlined
+ -- E.g. f = \x -> (++) ys
+ -- If we float, then eta-expand we get
+ -- lvl = (++) ys
+ -- f = \x \zs -> lvl zs
+ -- and now we'll inline lvl. Silly.
+
hasFreeJoin :: LevelEnv -> DVarSet -> Bool
-- Has a free join point which is not being floated to top level.
@@ -726,22 +735,22 @@ hasFreeJoin env fvs
The key idea in let-floating is to
* float a redex out of a (value) lambda
Doing so can save an unbounded amount of work.
-But see also Note [Saving allocation].
+But see also Note [Floating to the top].
So we definitely float an expression out if
-(a) It will escape a value lambda (escapes_value_lam)
-(b) The expression is not a head-normal form (exprIsHNF); see (SW1, SW2).
-(c) Floating does not require wrapping it in value lambdas (float_is_new_lam).
+(SW-a) It will escape a value lambda (escapes_value_lam)
+(SW-b) The expression is not a head-normal form (exprIsHNF); see (SW1, SW2).
+(SW-c) Floating does not require wrapping it in value lambdas (float_is_new_lam).
See (SW3) below
Wrinkles:
-(SW1) Concerning (b) I experimented with using `exprIsCheap` rather than
+(SW1) Concerning (SW-b) I experimented with using `exprIsCheap` rather than
`exprIsHNF` but the latter seems better, according to nofib
(`spectral/mate` got 10% worse with exprIsCheap). It's really a bit of a
heuristic.
-(SW2) What about omitting (b), and hence floating HNFs as well? The danger of
+(SW2) What about omitting (SW-b), and hence floating HNFs as well? The danger of
doing so is that we end up floating out a HNF from a cold path (where it
might never get allocated at all) and allocating it all the time
regardless. Example
@@ -760,7 +769,7 @@ Wrinkles:
- Occasionally decreases runtime allocation (T12996 -2.5%)
- Slightly mixed effect on nofib: (puzzle -10%, mate -5%, cichelli +5%)
but geometric mean is -0.09%.
- Overall, a win.
+ Overall, a small win.
(SW3) Concerning (c), if we are wrapping the thing in extra value lambdas (in
abs_vars), then nothing is saved. E.g.
@@ -771,10 +780,12 @@ Wrinkles:
we have saved nothing: one pair will still be allocated for each
call of `f`. Hence the (not float_is_new_lam) in saves_work.
-Note [Saving allocation]
-~~~~~~~~~~~~~~~~~~~~~~~~
+Note [Floating to the top]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
Even if `saves_work` is false, we we may want to float even cheap/HNF
-expressions out of value lambdas, for several reasons:
+expressions out of value lambdas. Data suggests, however, that it is better
+/only/ to do so, /if/ they can go to top level. If the expression goes to top
+level we don't pay the cost of allocating cold-path thunks described in (SW2).
* Doing so may save allocation. Consider
f = \x. .. (\y.e) ...
@@ -782,6 +793,11 @@ expressions out of value lambdas, for several reasons:
(assuming e does not mention x). An example where this really makes a
difference is simplrun009.
+* In principle this would be true even if the (\y.e) didn't go to top level; but
+ in practice we only float a HNF if it goes all way to the top. We don't pay
+ /any/ allocation cost for a top-level floated expression; it just becomes
+ static data.
+
* It may allow SpecContr to fire on functions. Consider
f = \x. ....(f (\y.e))....
After floating we get
@@ -793,21 +809,7 @@ expressions out of value lambdas, for several reasons:
a big difference for string literals and bottoming expressions: see Note
[Floating to the top]
-Data suggests, however, that it is better /only/ to float HNFS, /if/ they can go
-to top level. See (SW2) of Note [Saving work]. If the expression goes to top
-level we don't pay the cost of allocating cold-path thunks described in (SW2).
-
-Hence `isTopLvl dest_lvl` in `saves_alloc`.
-
-Note [Floating to the top]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-Even though Note [Saving allocation] suggests that we should not, in
-general, float HNFs, the balance change if it goes to the top:
-
-* We don't pay an allocation cost for the floated expression; it
- just becomes static data.
-
-* Floating string literal is valuable -- no point in duplicating the
+* Floating string literals is valuable -- no point in duplicating the
at each call site!
* Floating bottoming expressions is valuable: they are always cold
@@ -815,32 +817,32 @@ general, float HNFs, the balance change if it goes to the top:
can be quite big, inhibiting inlining. See Note [Bottoming floats]
So we float an expression to the top if:
- (a) the context is lazy (so we get allocation), or
- (b) the expression is a HNF (so we get allocation), or
- (c) the expression is bottoming and floating would escape a
- value lambda (NB: if the expression itself is a lambda, (b)
- will apply; so this case only catches bottoming thunks)
+ (FT1) the context is lazy (so we get allocation), or
+ (FT2) the expression is a HNF (so we get allocation), or
+ (FT3) the expression is bottoming and floating would escape a
+ value lambda (NB: if the expression itself is a lambda, (b)
+ will apply; so this case only catches bottoming thunks)
Examples:
-* (a) Strict. Case scrutinee
+* (FT1) Strict. Case scrutinee
f = case g True of ....
Don't float (g True) to top level; then we have the admin of a
top-level thunk to worry about, with zero gain.
-* (a) Strict. Case alternative
+* (FT1) Strict. Case alternative
h = case y of
True -> g True
False -> False
Don't float (g True) to the top level
-* (b) HNF
+* (FT2) HNF
f = case y of
True -> p:q
False -> blah
We may as well float the (p:q) so it becomes a static data structure.
-* (c) Bottoming expressions; see also Note [Bottoming floats]
+* (FT3) Bottoming expressions; see also Note [Bottoming floats]
f x = case x of
0 -> error <big thing>
_ -> x+1
@@ -853,7 +855,7 @@ Examples:
'foo' anyway. So float bottoming things only if they escape
a lambda.
-* Arguments
+* (FT4) Arguments
t = f (g True)
Prior to Apr 22 we didn't float (g True) to the top if f was strict.
But (a) this only affected CAFs, because if it escapes a value lambda
@@ -868,28 +870,6 @@ early loses opportunities for RULES which (needless to say) are
important in some nofib programs (gcd is an example). [SPJ note:
I think this is obsolete; the flag seems always on.]
-Note [Large free-variable sets]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In #24471 we had something like
- x1 = I# 1
- ...
- x1000 = I# 1000
- foo = f x1 (f x2 (f x3 ....))
-So every sub-expression in `foo` has lots and lots of free variables. But
-none of these sub-expressions float anywhere; the entire float-out pass is a
-no-op.
-
-In lvlMFE, we want to find out quickly if the MFE is not-floatable; that is
-the common case. In #24471 it turned out that we were testing `abs_vars` (a
-relatively complicated calculation that takes at least O(n-free-vars) time to
-compute) for every sub-expression.
-
-Better instead to test `float_me` early. That still involves looking at
-dest_lvl, which means looking at every free variable, but the constant factor
-is a lot better.
-
-ToDo: find a way to fix the bad asymptotic complexity.
-
Note [Floating join point bindings]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Mostly we don't float join points at all -- we want them to /stay/ join points.
@@ -1053,30 +1033,36 @@ we'd like to float the call to error, to get
But, as ever, we need to be careful:
-(1) We want to float a bottoming
+(BF1) We want to float a bottoming
expression even if it has free variables:
f = \x. g (let v = h x in error ("urk" ++ v))
Then we'd like to abstract over 'x', and float the whole arg of g:
lvl = \x. let v = h x in error ("urk" ++ v)
f = \x. g (lvl x)
- To achieve this we pass is_bot to destLevel
-
-(2) We do not do this for lambdas that return
- bottom. Instead we treat the /body/ of such a function specially,
- via point (1). For example:
+ To achieve this we pass `is_bot` to destLevel
+
+(BF2) We do the same for /lambdas/ that return bottom.
+ Suppose the original lambda had /no/ free vars:
+ f = \x. ....(\y z. error (y++z))...
+ then we'd like to float that whole lambda
+ lvl = \y z. error (y++z)
+ f = \x. ....lvl....
+ If we just floated its bottom-valued body, we might abstract the arguments in
+ the "wrong" order and end up with this bad result
+ lvl = \z y. error (y++z)
+ f = \x. ....(\y z. lvl z y)....
+
+ If the lambda does have free vars, this will happen:
f = \x. ....(\y z. if x then error y else error z)....
- If we float the whole lambda thus
+ We float the whole lambda thus
lvl = \x. \y z. if x then error y else error z
f = \x. ...(lvl x)...
- we may well end up eta-expanding that PAP to
+ And we may well end up eta-expanding that PAP to
+ lvl = \x. \y z. if b then error y else error z
f = \x. ...(\y z. lvl x y z)...
+ so we get a (small) closure. So be it.
- ===>
- lvl = \x z y. if b then error y else error z
- f = \x. ...(\y z. lvl x z y)...
- (There is no guarantee that we'll choose the perfect argument order.)
-
-(3) If we have a /binding/ that returns bottom, we want to float it to top
+(BF3) If we have a /binding/ that returns bottom, we want to float it to top
level, even if it has free vars (point (1)), and even it has lambdas.
Example:
... let { v = \y. error (show x ++ show y) } in ...
@@ -1092,7 +1078,6 @@ But, as ever, we need to be careful:
join points (#24768), and floating to the top would abstract over those join
points, which we should never do.
-
See Maessen's paper 1999 "Bottom extraction: factoring error handling out
of functional programs" (unpublished I think).
@@ -1135,7 +1120,6 @@ float the case (as advocated here) we won't float the (build ...y..)
either, so fusion will happen. It can be a big effect, esp in some
artificial benchmarks (e.g. integer, queens), but there is no perfect
answer.
-
-}
annotateBotStr :: Id -> Arity -> Maybe (Arity, DmdSig, CprSig) -> Id
@@ -1152,69 +1136,124 @@ annotateBotStr id n_extra mb_bot_str
= id
notWorthFloating :: CoreExpr -> [Var] -> Bool
--- Returns True if the expression would be replaced by
--- something bigger than it is now. For example:
--- abs_vars = tvars only: return True if e is trivial,
--- but False for anything bigger
--- abs_vars = [x] (an Id): return True for trivial, or an application (f x)
--- but False for (f x x)
---
--- One big goal is that floating should be idempotent. Eg if
--- we replace e with (lvl79 x y) and then run FloatOut again, don't want
--- to replace (lvl79 x y) with (lvl83 x y)!
-
+-- See Note [notWorthFloating]
notWorthFloating e abs_vars
- = go e (count isId abs_vars)
+ = go e 0
where
- go (Var {}) n = n >= 0
- go (Lit lit) n = assert (n==0) $
- litIsTrivial lit -- Note [Floating literals]
- go (Type {}) _ = True
- go (Coercion {}) _ = True
+ n_abs_vars = count isId abs_vars -- See (NWF5)
+
+ go :: CoreExpr -> Int -> Bool
+ -- (go e n) return True if (e x1 .. xn) is not worth floating
+ -- where `e` has n trivial value arguments x1..xn
+ -- See (NWF4)
+ go (Lit lit) n = assert (n==0) $
+ litIsTrivial lit -- See (NWF1)
+ go (Type {}) _ = True
+ go (Tick t e) n = not (tickishIsCode t) && go e n
+ go (Cast e _) n = n==0 || go e n -- See (NWF3)
+ go (Coercion {}) _ = True
go (App e arg) n
- -- See Note [Floating applications to coercions]
- | not (isRuntimeArg arg) = go e n
- | n==0 = False
- | exprIsTrivial arg = go e (n-1) -- NB: exprIsTrivial arg = go arg 0
- | otherwise = False
- go (Tick t e) n = not (tickishIsCode t) && go e n
- go (Cast e _) n = go e n
- go (Case e b _ as) n
+ | Type {} <- arg = go e n -- Just types, not coercions (NWF2)
+ | exprIsTrivial arg = go e (n+1)
+ | otherwise = False -- (f non-triv) is worth floating
+
+ go (Case e b _ as) _
+ -- Do not float the `case` part of trivial cases (NWF3)
+ -- We'll have a look at the RHS when we get there
| null as
- = go e n -- See Note [Empty case is trivial]
- | Just rhs <- isUnsafeEqualityCase e b as
- = go rhs n -- See (U2) of Note [Implementing unsafeCoerce] in base:Unsafe.Coerce
- go _ _ = False
+ = True -- See Note [Empty case is trivial]
+ | Just {} <- isUnsafeEqualityCase e b as
+ = True -- See (U2) of Note [Implementing unsafeCoerce] in base:Unsafe.Coerce
+ | otherwise
+ = False
-{-
-Note [Floating literals]
-~~~~~~~~~~~~~~~~~~~~~~~~
-It's important to float Integer literals, so that they get shared,
-rather than being allocated every time round the loop.
-Hence the litIsTrivial.
+ go (Var _) n
+ | n==0 = True -- Naked variable
+ | n <= n_abs_vars = True -- (f a b c) is not worth floating if
+ | otherwise = False -- a,b,c are all abstracted; see (NWF5)
-Ditto literal strings (LitString), which we'd like to float to top
-level, which is now possible.
+ go _ _ = False -- Let etc is worth floating
-Note [Floating applications to coercions]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We don’t float out variables applied only to type arguments, since the
-extra binding would be pointless: type arguments are completely erased.
-But *coercion* arguments aren’t (see Note [Coercion tokens] in
-"GHC.CoreToStg" and Note [inlineBoringOk] in"GHC.Core.Unfold"),
-so we still want to float out variables applied only to
-coercion arguments.
+{- Note [notWorthFloating]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+`notWorthFloating` returns True if the expression would be replaced by something
+bigger than it is now. One big goal is that floating should be idempotent. Eg
+if we replace e with (lvl79 x y) and then run FloatOut again, don't want to
+replace (lvl79 x y) with (lvl83 x y)!
+For example:
+ abs_vars = tvars only: return True if e is trivial,
+ but False for anything bigger
+ abs_vars = [x] (an Id): return True for trivial, or an application (f x)
+ but False for (f x x)
+
+(NWF1) It's important to float Integer literals, so that they get shared, rather
+ than being allocated every time round the loop. Hence the litIsTrivial.
+
+ Ditto literal strings (LitString), which we'd like to float to top
+ level, which is now possible.
+
+(NWF2) We don’t float out variables applied only to type arguments, since the
+ extra binding would be pointless: type arguments are completely erased.
+ But *coercion* arguments aren’t (see Note [Coercion tokens] in
+ "GHC.CoreToStg" and Note [inlineBoringOk] in"GHC.Core.Unfold"),
+ so we still want to float out variables applied only to
+ coercion arguments.
+
+(NWF3) Some expressions have trivial wrappers:
+ - Casts (e |> co)
+ - Unary-class applications:
+ - Dictionary applications (MkC meth)
+ - Class-op applictions (op dict)
+ - Case of empty alts
+ - Unsafe-equality case
+ In all these cases we say "not worth floating", and we do so /regardless/
+ of the wrapped expression. The SetLevels stuff may subsequently float the
+ components of the expression.
+
+ Example: is it worth floating (f x |> co)? No! If we did we'd get
+ lvl = f x |> co
+ ...lvl....
+ Then we'd do cast worker/wrapper and end up with.
+ lvl' = f x
+ ...(lvl' |> co)...
+ Silly! Better not to float it in the first place. If we say "no" here,
+ we'll subsequently say "yes" for (f x) and get
+ lvl = f x
+ ....(lvl |> co)...
+ which is what we want. In short: don't float trivial wrappers.
+
+(NWF4) The only non-trivial expression that we say "not worth floating" for
+ is an application
+ f x y z
+ where the number of value arguments is <= the number of abstracted Ids.
+ This is what makes floating idempotent. Hence counting the number of
+ value arguments in `go`
+
+(NWF5) In #24471 we had something like
+ x1 = I# 1
+ ...
+ x1000 = I# 1000
+ foo = f x1 (f x2 (f x3 ....))
+ So every sub-expression in `foo` has lots and lots of free variables. But
+ none of these sub-expressions float anywhere; the entire float-out pass is a
+ no-op.
-************************************************************************
-* *
-\subsection{Bindings}
-* *
-************************************************************************
+ So `notWorthFloating` tries to avoid evaluating `n_abs_vars`, in cases where
+ it obviously /is/ worth floating. (In #24471 it turned out that we were
+ testing `abs_vars` (a relatively complicated calculation that takes at least
+ O(n-free-vars) time to compute) for every sub-expression.)
-The binding stuff works for top level too.
+ Hence testing `n_abs_vars only` at the very end.
-}
+{- *********************************************************************
+* *
+ Bindings
+ This binding stuff works for top level too.
+* *
+********************************************************************* -}
+
lvlBind :: LevelEnv
-> CoreBindWithFVs
-> LvlM (LevelledBind, LevelEnv)
@@ -1261,7 +1300,7 @@ lvlBind env (AnnNonRec bndr rhs)
-- is_bot_lam: looks like (\xy. bot), maybe zero lams
-- NB: not isBottomThunk!
-- NB: not is_join: don't send bottoming join points to the top.
- -- See Note [Bottoming floats] point (3)
+ -- See Note [Bottoming floats] (BF3)
is_top_bindable = exprIsTopLevelBindable deann_rhs bndr_ty
n_extra = count isId abs_vars
@@ -1552,9 +1591,8 @@ destLevel env fvs fvs_ty is_function is_bot
-- See Note [Floating join point bindings]
= tOP_LEVEL
- | is_bot -- Send bottoming bindings to the top
- = as_far_as_poss -- regardless; see Note [Bottoming floats]
- -- Esp Bottoming floats (1) and (3)
+ | is_bot -- Send bottoming bindings to the top regardless;
+ = as_far_as_poss -- see (BF1) and (BF2) in Note [Bottoming floats]
| Just n_args <- floatLams env
, n_args > 0 -- n=0 case handled uniformly by the 'otherwise' case
@@ -1568,8 +1606,13 @@ destLevel env fvs fvs_ty is_function is_bot
max_fv_id_level = maxFvLevel isId env fvs -- Max over Ids only; the
-- tyvars will be abstracted
+ -- as_far_as_poss: destination level depends only on the free Ids (more
+ -- precisely, free CoVars) of the /type/, not the free Ids of the /term/.
+ -- Why worry about the free CoVars? See Note [Floating and kind casts]
+ --
+ -- There may be free Ids in the term, but then we'll just
+ -- lambda-abstract over them
as_far_as_poss = maxFvLevel' isId env fvs_ty
- -- See Note [Floating and kind casts]
{- Note [Floating and kind casts]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1732,10 +1775,9 @@ maxFvLevel max_me env var_set
-- It's OK to use a non-deterministic fold here because maxIn commutes.
maxFvLevel' :: (Var -> Bool) -> LevelEnv -> TyCoVarSet -> Level
--- Same but for TyCoVarSet
+-- Precisely the same as `maxFvLevel` but for TyCoVarSet rather than DVarSet
maxFvLevel' max_me env var_set
= nonDetStrictFoldUniqSet (maxIn max_me env) tOP_LEVEL var_set
- -- It's OK to use a non-deterministic fold here because maxIn commutes.
maxIn :: (Var -> Bool) -> LevelEnv -> InVar -> Level -> Level
maxIn max_me (LE { le_lvl_env = lvl_env, le_env = id_env }) in_var lvl
=====================================
compiler/GHC/Core/Opt/Simplify/Env.hs
=====================================
@@ -11,7 +11,7 @@ module GHC.Core.Opt.Simplify.Env (
SimplMode(..), updMode, smPlatform,
-- * Environments
- SimplEnv(..), pprSimplEnv, -- Temp not abstract
+ SimplEnv(..), StaticEnv, pprSimplEnv,
seArityOpts, seCaseCase, seCaseFolding, seCaseMerge, seCastSwizzle,
seDoEtaReduction, seEtaExpand, seFloatEnable, seInline, seNames,
seOptCoercionOpts, sePhase, sePlatform, sePreInline,
@@ -170,6 +170,8 @@ coercion we don't apply optCoercion to it if seInlineDepth>0.
Reason: it has already been optimised once, no point in doing so again.
-}
+type StaticEnv = SimplEnv -- Just the static part is relevant
+
data SimplEnv
= SimplEnv {
----------- Static part of the environment -----------
@@ -407,7 +409,6 @@ data SimplSR
-- and ja = Just a <=> x is a join-point of arity a
-- See Note [Join arity in SimplIdSubst]
-
| DoneId OutId
-- If x :-> DoneId v is in the SimplIdSubst
-- then replace occurrences of x by v
@@ -778,7 +779,7 @@ emptyJoinFloats = nilOL
isEmptyJoinFloats :: JoinFloats -> Bool
isEmptyJoinFloats = isNilOL
-unitLetFloat :: OutBind -> LetFloats
+unitLetFloat :: HasDebugCallStack => OutBind -> LetFloats
-- This key function constructs a singleton float with the right form
unitLetFloat bind = assert (all (not . isJoinId) (bindersOf bind)) $
LetFloats (unitOL bind) (flag bind)
=====================================
compiler/GHC/Core/Opt/Simplify/Iteration.hs
=====================================
@@ -447,7 +447,7 @@ we want to do something very similar to worker/wrapper:
We call this making a cast worker/wrapper in tryCastWorkerWrapper.
-The main motivaiton is that x can be inlined freely. There's a chance
+The main motivation is that x can be inlined freely. There's a chance
that e will be a constructor application or function, or something
like that, so moving the coercion to the usage site may well cancel
the coercions and lead to further optimisation. Example:
@@ -576,11 +576,13 @@ Note [Concrete types] in GHC.Tc.Utils.Concrete.
-}
tryCastWorkerWrapper :: SimplEnv -> BindContext
- -> InId -> OutId -> OutExpr
- -> SimplM (SimplFloats, SimplEnv)
+ -> OutId -> OutExpr
+ -> SimplM (Maybe (LetFloats, OutId, OutExpr))
-- See Note [Cast worker/wrapper]
-tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co)
- | BC_Let top_lvl is_rec <- bind_cxt -- Not join points
+-- Given input x = rhs |> co, the result will be
+-- (x' = rhs, x, x' |> co))
+tryCastWorkerWrapper env bind_cxt bndr (Cast rhs co)
+ | BC_Let top_lvl _ <- bind_cxt -- Not join points
, not (isDFunId bndr) -- nor DFuns; cast w/w is no help, and we can't transform
-- a DFunUnfolding in mk_worker_unfolding
, not (exprIsTrivial rhs) -- Not x = y |> co; Wrinkle 1
@@ -588,38 +590,23 @@ tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co)
, typeHasFixedRuntimeRep work_ty -- Don't peel off a cast if doing so would
-- lose the underlying runtime representation.
-- See Note [Preserve RuntimeRep info in cast w/w]
- , not (isOpaquePragma (idInlinePragma old_bndr)) -- Not for OPAQUE bindings
- -- See Note [OPAQUE pragma]
+ , not (isOpaquePragma (idInlinePragma bndr)) -- Not for OPAQUE bindings
+ -- See Note [OPAQUE pragma]
= do { uniq <- getUniqueM
; let work_name = mkSystemVarName uniq occ_fs
work_id = mkLocalIdWithInfo work_name ManyTy work_ty work_info
- is_strict = isStrictId bndr
- ; (rhs_floats, work_rhs) <- prepareBinding env top_lvl is_rec is_strict
- work_id (emptyFloats env) rhs
-
- ; work_unf <- mk_worker_unfolding top_lvl work_id work_rhs
+ ; work_unf <- mk_worker_unfolding top_lvl work_id rhs
; let work_id_w_unf = work_id `setIdUnfolding` work_unf
- floats = rhs_floats `addLetFloats`
- unitLetFloat (NonRec work_id_w_unf work_rhs)
-
- triv_rhs = Cast (Var work_id_w_unf) co
-
- ; if postInlineUnconditionally env bind_cxt old_bndr bndr triv_rhs
- -- Almost always True, because the RHS is trivial
- -- In that case we want to eliminate the binding fast
- -- We conservatively use postInlineUnconditionally so that we
- -- check all the right things
- then do { tick (PostInlineUnconditionally bndr)
- ; return ( floats
- , extendIdSubst (setInScopeFromF env floats) old_bndr $
- DoneEx triv_rhs NotJoinPoint ) }
-
- else do { wrap_unf <- mkLetUnfolding env top_lvl VanillaSrc bndr False triv_rhs
- ; let bndr' = bndr `setInlinePragma` mkCastWrapperInlinePrag (idInlinePragma bndr)
- `setIdUnfolding` wrap_unf
- floats' = floats `extendFloats` NonRec bndr' triv_rhs
- ; return ( floats', setInScopeFromF env floats' ) } }
+ work_bind = NonRec work_id_w_unf rhs
+ triv_rhs = Cast (Var work_id_w_unf) co
+
+ ; wrap_unf <- mkLetUnfolding env top_lvl VanillaSrc bndr False triv_rhs
+ ; let wrap_prag = mkCastWrapperInlinePrag (inlinePragInfo info)
+ bndr' = bndr `setInlinePragma` wrap_prag
+ `setIdUnfolding` wrap_unf
+
+ ; return (Just (unitLetFloat work_bind, bndr', triv_rhs)) }
where
-- Force the occ_fs so that the old Id is not retained in the new Id.
!occ_fs = getOccFS bndr
@@ -647,10 +634,10 @@ tryCastWorkerWrapper env bind_cxt old_bndr bndr (Cast rhs co)
| isStableSource src -> return (unf { uf_tmpl = mkCast unf_rhs (mkSymCo co) })
_ -> mkLetUnfolding env top_lvl VanillaSrc work_id False work_rhs
-tryCastWorkerWrapper env _ _ bndr rhs -- All other bindings
+tryCastWorkerWrapper _ _ bndr rhs -- All other bindings
= do { traceSmpl "tcww:no" (vcat [ text "bndr:" <+> ppr bndr
, text "rhs:" <+> ppr rhs ])
- ; return (mkFloatBind env (NonRec bndr rhs)) }
+ ; return Nothing }
mkCastWrapperInlinePrag :: InlinePragma -> InlinePragma
-- See Note [Cast worker/wrapper]
@@ -810,39 +797,40 @@ makeTrivial :: HasDebugCallStack
-- Binds the expression to a variable, if it's not trivial, returning the variable
-- For the Demand argument, see Note [Keeping demand info in StrictArg Plan A]
makeTrivial env top_lvl dmd occ_fs expr
- | exprIsTrivial expr -- Already trivial
- || not (bindingOk top_lvl expr expr_ty) -- Cannot trivialise
- -- See Note [Cannot trivialise]
+ | exprIsTrivial expr -- Already trivial
= return (emptyLetFloats, expr)
- | Cast expr' co <- expr
- = do { (floats, triv_expr) <- makeTrivial env top_lvl dmd occ_fs expr'
- ; return (floats, Cast triv_expr co) }
+ | not (bindingOk top_lvl expr expr_ty) -- Cannot trivialise
+ = return (emptyLetFloats, expr) -- See Note [Cannot trivialise]
- | otherwise -- 'expr' is not of form (Cast e co)
+ | otherwise
= do { (floats, expr1) <- prepareRhs env top_lvl occ_fs expr
; uniq <- getUniqueM
; let name = mkSystemVarName uniq occ_fs
- var = mkLocalIdWithInfo name ManyTy expr_ty id_info
+ bndr = mkLocalIdWithInfo name ManyTy expr_ty id_info
+ bind_ctxt = BC_Let top_lvl NonRecursive
-- Now something very like completeBind,
-- but without the postInlineUnconditionally part
- ; (arity_type, expr2) <- tryEtaExpandRhs env (BC_Let top_lvl NonRecursive) var expr1
+ ; (arity_type, expr2) <- tryEtaExpandRhs env bind_ctxt bndr expr1
-- Technically we should extend the in-scope set in 'env' with
-- the 'floats' from prepareRHS; but they are all fresh, so there is
-- no danger of introducing name shadowing in eta expansion
- ; unf <- mkLetUnfolding env top_lvl VanillaSrc var False expr2
-
- ; let final_id = addLetBndrInfo var arity_type unf
- bind = NonRec final_id expr2
+ ; unf <- mkLetUnfolding env top_lvl VanillaSrc bndr False expr2
+ ; let bndr' = addLetBndrInfo bndr arity_type unf
+ anf_bind = NonRec bndr' expr2
- ; traceSmpl "makeTrivial" (vcat [text "final_id" <+> ppr final_id, text "rhs" <+> ppr expr2 ])
- ; return ( floats `addLetFlts` unitLetFloat bind, Var final_id ) }
+ ; mb_cast_ww <- tryCastWorkerWrapper env bind_ctxt bndr' expr2
+ ; case mb_cast_ww of
+ Nothing -> return (floats `addLetFlts` unitLetFloat anf_bind, Var bndr')
+ Just (work_flts, _, triv_rhs)
+ -> return (floats `addLetFlts` work_flts, triv_rhs) }
where
id_info = vanillaIdInfo `setDemandInfo` dmd
expr_ty = exprType expr
+
bindingOk :: TopLevelFlag -> CoreExpr -> Type -> Bool
-- True iff we can have a binding of this expression at this level
-- Precondition: the type is the type of the expression
@@ -936,26 +924,50 @@ completeBind bind_cxt (old_bndr, unf_se) (new_bndr, new_rhs, env)
eta_rhs (idType new_bndr) new_arity old_unf
; let new_bndr_w_info = addLetBndrInfo new_bndr new_arity new_unfolding
- -- See Note [In-scope set as a substitution]
+ -- See Note [In-scope set as a substitution]
+ occ_anald_rhs = maybeUnfoldingTemplate new_unfolding `orElse` eta_rhs
+ -- occ_anald_rhs: see Note [Use occ-anald RHS in postInlineUnconditionally]
+ -- Try postInlineUnconditionally for (x = rhs)
+ -- If that succeeds we don't want to do tryCastWorkerWrapper
; if postInlineUnconditionally env bind_cxt old_bndr new_bndr_w_info eta_rhs
-
- then -- Inline and discard the binding
- do { tick (PostInlineUnconditionally old_bndr)
- ; let unf_rhs = maybeUnfoldingTemplate new_unfolding `orElse` eta_rhs
- -- See Note [Use occ-anald RHS in postInlineUnconditionally]
- ; simplTrace "PostInlineUnconditionally" (ppr new_bndr <+> ppr unf_rhs) $
- return ( emptyFloats env
- , extendIdSubst env old_bndr $
- DoneEx unf_rhs (idJoinPointHood new_bndr)) }
+ then post_inline_it (emptyFloats env) occ_anald_rhs
+ else
+
+ do { -- Try cast worker-wrapper
+ mb_cast_ww <- tryCastWorkerWrapper env bind_cxt new_bndr_w_info eta_rhs
+ ; case mb_cast_ww of
+ Nothing -> no_post_inline (emptyFloats env) new_bndr_w_info eta_rhs
+
+ Just (cast_let_flts, new_bndr, new_rhs)
+ -- Try postInlineUnconditionally for (new_bndr = new_rhs)
+ -- Almost always fires, because `new_rhs` is small, but we conservatively
+ -- use `postInlineUnconditionally` so that we check all the right things
+ | postInlineUnconditionally env bind_cxt old_bndr new_bndr new_rhs
+ -> post_inline_it cast_floats new_rhs
+ -- new_rhs is (x |> co) so no need to occ-anal
+ | otherwise
+ -> no_post_inline cast_floats new_bndr new_rhs
+ where
+ cast_floats = emptyFloats env `addLetFloats` cast_let_flts
+ } }
+ where
+ no_post_inline floats new_bndr new_rhs
+ = do { let the_bind = NonRec new_bndr new_rhs
+ floats' = floats `extendFloats` the_bind
+ env' = env `setInScopeFromF` floats'
+ ; return (floats', env') }
+
+ post_inline_it floats rhs
+ = do { simplTrace "PostInlineUnconditionally" (ppr old_bndr <+> ppr rhs) $
+ tick (PostInlineUnconditionally old_bndr)
+ ; let env' = env `setInScopeFromF` floats
+ ; return ( floats
+ , extendIdSubst env' old_bndr $
+ DoneEx rhs (idJoinPointHood old_bndr)) }
-- Use the substitution to make quite, quite sure that the
-- substitution will happen, since we are going to discard the binding
- else -- Keep the binding; do cast worker/wrapper
--- simplTrace "completeBind" (vcat [ text "bndrs" <+> ppr old_bndr <+> ppr new_bndr
--- , text "eta_rhs" <+> ppr eta_rhs ]) $
- tryCastWorkerWrapper env bind_cxt old_bndr new_bndr_w_info eta_rhs }
-
addLetBndrInfo :: OutId -> ArityType -> Unfolding -> OutId
addLetBndrInfo new_bndr new_arity_type new_unf
= new_bndr `setIdInfo` info5
@@ -3955,7 +3967,17 @@ mkDupableContWithDmds env dmds
; (floats1, cont') <- mkDupableContWithDmds env cont_dmds cont
; let env' = env `setInScopeFromF` floats1
; (_, se', arg') <- simplLazyArg env' dup hole_ty Nothing se arg
- ; (let_floats2, arg'') <- makeTrivial env NotTopLevel dmd (fsLit "karg") arg'
+
+ -- Make the argument duplicable. Danger: if arg is small and we let-bind
+ -- it, then postInlineUnconditionally will just inline it again, perhaps
+ -- taking an extra Simplifier iteration (e.g. in test T21839c). So make
+ -- a `let` only if `couldBeSmallEnoughToInline` says that it is big enough
+ ; let uf_opts = seUnfoldingOpts env
+ ; (let_floats2, arg'')
+ <- if couldBeSmallEnoughToInline uf_opts (unfoldingUseThreshold uf_opts) arg'
+ then return (emptyLetFloats, arg')
+ else makeTrivial env NotTopLevel dmd (fsLit "karg") arg'
+
; let all_floats = floats1 `addLetFloats` let_floats2
; return ( all_floats
, ApplyToVal { sc_arg = arg''
@@ -4592,7 +4614,8 @@ mkLetUnfolding :: SimplEnv -> TopLevelFlag -> UnfoldingSource
-> InId -> Bool -- True <=> this is a join point
-> OutExpr -> SimplM Unfolding
mkLetUnfolding env top_lvl src id is_join new_rhs
- = return (mkUnfolding uf_opts src is_top_lvl is_bottoming is_join new_rhs Nothing)
+ = -- Monadic to force those where-bindings
+ return (mkUnfolding uf_opts src is_top_lvl is_bottoming is_join new_rhs Nothing)
-- We make an unfolding *even for loop-breakers*.
-- Reason: (a) It might be useful to know that they are WHNF
-- (b) In GHC.Iface.Tidy we currently assume that, if we want to
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -216,8 +216,6 @@ data SimplCont
CoreTickish -- Tick tickish <hole>
SimplCont
-type StaticEnv = SimplEnv -- Just the static part is relevant
-
data FromWhat = FromLet | FromBeta Levity
-- See Note [DupFlag invariants]
@@ -723,7 +721,6 @@ which it is on the LHS of a rule (see updModeForRules), then don't
make use of the strictness info for the function.
-}
-
{-
************************************************************************
* *
@@ -1423,8 +1420,12 @@ preInlineUnconditionally for
Note [Top-level bottoming Ids]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Don't inline top-level Ids that are bottoming, even if they are used just
-once, because FloatOut has gone to some trouble to extract them out.
-Inlining them won't make the program run faster!
+once, because FloatOut has gone to some trouble to extract them out. e.g.
+ report x y = error (..lots of stuff...)
+ f x y z = if z then report x y else ...blah...
+Here `f` might be small enough to inline; but if we put all the `report`
+stuff inside it, it'll look to big. In general we don't want to duplicate
+all the error-reporting goop.
Note [Do not inline CoVars unconditionally]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1460,51 +1461,25 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
extend_subst_with inl_rhs = extendIdSubst env bndr $! (mkContEx rhs_env inl_rhs)
one_occ IAmDead = True -- Happens in ((\x.1) v)
- one_occ OneOcc{ occ_n_br = 1
- , occ_in_lam = NotInsideLam } = isNotTopLevel top_lvl || early_phase
+ one_occ OneOcc{ occ_n_br = 1
+ , occ_in_lam = NotInsideLam
+ , occ_int_cxt = int_cxt }
+ = isNotTopLevel top_lvl -- Get rid of allocation
+ || (int_cxt==IsInteresting) -- Function is applied
+ -- || (early_phase && not (isConLikeUnfolding unf)) -- See early_phase
one_occ OneOcc{ occ_n_br = 1
, occ_in_lam = IsInsideLam
- , occ_int_cxt = IsInteresting } = canInlineInLam rhs
- one_occ _ = False
+ , occ_int_cxt = IsInteresting }
+ = canInlineInLam rhs
+ one_occ _
+ = False
pre_inline_unconditionally = sePreInline env
active = isActive (sePhase env) (inlinePragmaActivation inline_prag)
-- See Note [pre/postInlineUnconditionally in gentle mode]
inline_prag = idInlinePragma bndr
--- Be very careful before inlining inside a lambda, because (a) we must not
--- invalidate occurrence information, and (b) we want to avoid pushing a
--- single allocation (here) into multiple allocations (inside lambda).
--- Inlining a *function* with a single *saturated* call would be ok, mind you.
--- || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
--- where
--- is_cheap = exprIsCheap rhs
--- ok = is_cheap && int_cxt
-
- -- int_cxt The context isn't totally boring
- -- E.g. let f = \ab.BIG in \y. map f xs
- -- Don't want to substitute for f, because then we allocate
- -- its closure every time the \y is called
- -- But: let f = \ab.BIG in \y. map (f y) xs
- -- Now we do want to substitute for f, even though it's not
- -- saturated, because we're going to allocate a closure for
- -- (f y) every time round the loop anyhow.
-
- -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
- -- so substituting rhs inside a lambda doesn't change the occ info.
- -- Sadly, not quite the same as exprIsHNF.
- canInlineInLam (Lit _) = True
- canInlineInLam (Lam b e) = isRuntimeVar b || canInlineInLam e
- canInlineInLam (Tick t e) = not (tickishIsCode t) && canInlineInLam e
- canInlineInLam (Var v) = case idOccInfo v of
- OneOcc { occ_in_lam = IsInsideLam } -> True
- ManyOccs {} -> True
- _ -> False
- canInlineInLam _ = False
- -- not ticks. Counting ticks cannot be duplicated, and non-counting
- -- ticks around a Lam will disappear anyway.
-
- early_phase = sePhase env /= FinalPhase
+-- early_phase = sePhase env /= FinalPhase
-- If we don't have this early_phase test, consider
-- x = length [1,2,3]
-- The full laziness pass carefully floats all the cons cells to
@@ -1532,6 +1507,52 @@ preInlineUnconditionally env top_lvl bndr rhs rhs_env
-- (Nor can we check for `exprIsExpandable rhs`, because that needs to look
-- at the non-existent unfolding for the `I# 2#` which is also floated out.)
+
+-- Be very careful before inlining inside a lambda, because (a) we must not
+-- invalidate occurrence information, and (b) we want to avoid pushing a
+-- single allocation (here) into multiple allocations (inside lambda).
+-- Inlining a *function* with a single *saturated* call would be ok, mind you.
+-- || (if is_cheap && not (canInlineInLam rhs) then pprTrace "preinline" (ppr bndr <+> ppr rhs) ok else ok)
+-- where
+-- is_cheap = exprIsCheap rhs
+-- ok = is_cheap && int_cxt
+
+ -- int_cxt The context isn't totally boring
+ -- E.g. let f = \ab.BIG in \y. map f xs
+ -- Don't want to substitute for f, because then we allocate
+ -- its closure every time the \y is called
+ -- But: let f = \ab.BIG in \y. map (f y) xs
+ -- Now we do want to substitute for f, even though it's not
+ -- saturated, because we're going to allocate a closure for
+ -- (f y) every time round the loop anyhow.
+
+ -- canInlineInLam => free vars of rhs are (Once in_lam) or Many,
+ -- so substituting rhs inside a lambda doesn't change the occ info.
+ -- Sadly, not quite the same as exprIsHNF.
+canInlineInLam ::CoreExpr -> Bool
+canInlineInLam e
+ = go e
+ where
+ go (Lit _) = True
+ go (Lam b e) = isRuntimeVar b || go e
+ go (Cast e _) = go e
+ go (Tick t e) = not (tickishIsCode t) && go e
+ -- This matters only for:
+ -- x = y -- or y|>co
+ -- f = \p. ..x.. -- One occurrence of x
+ -- ..y.. -- Multiple other occurrences of y
+ -- Then it is safe to inline x unconditionally
+ -- For postInlineUncondionally we have already tested exprIsTrivial
+ -- so this Var case never arises
+ go (Var v) = case idOccInfo v of
+ OneOcc { occ_in_lam = IsInsideLam } -> True
+ ManyOccs {} -> True
+ _ -> False
+ go _ = False
+ -- not ticks. Counting ticks cannot be duplicated, and non-counting
+ -- ticks around a Lam will disappear anyway.
+
+
{-
************************************************************************
* *
@@ -1582,71 +1603,77 @@ postInlineUnconditionally
-- Reason: we don't want to inline single uses, or discard dead bindings,
-- for unlifted, side-effect-ful bindings
postInlineUnconditionally env bind_cxt old_bndr bndr rhs
- | not active = False
- | isWeakLoopBreaker occ_info = False -- If it's a loop-breaker of any kind, don't inline
- -- because it might be referred to "earlier"
- | isStableUnfolding unfolding = False -- Note [Stable unfoldings and postInlineUnconditionally]
- | isTopLevel (bindContextLevel bind_cxt)
- = False -- Note [Top level and postInlineUnconditionally]
- | exprIsTrivial rhs = True
- | BC_Join {} <- bind_cxt = False -- See point (1) of Note [Duplicating join points]
+ | not active = False
+ | isWeakLoopBreaker occ_info = False -- If it's a loop-breaker of any kind, don't inline
+ -- because it might be referred to "earlier"
+ | isStableUnfolding unfolding = False -- Note [Stable unfoldings and postInlineUnconditionally]
+ | BC_Join {} <- bind_cxt = exprIsTrivial rhs
+ -- See point (DJ1) of Note [Duplicating join points]
-- in GHC.Core.Opt.Simplify.Iteration
+ | is_top_lvl, isDeadEndId bndr = False -- Note [Top-level bottoming Ids]
| otherwise
= case occ_info of
- OneOcc { occ_in_lam = in_lam, occ_int_cxt = int_cxt, occ_n_br = n_br }
- -- See Note [Inline small things to avoid creating a thunk]
+ IAmALoopBreaker {} -> False
+ ManyOccs {} | is_top_lvl -> False -- Note [Top level and postInlineUnconditionally]
+ | otherwise -> exprIsTrivial rhs
- | n_br >= 100 -> False -- See #23627
+ OneOcc { occ_in_lam = in_lam, occ_int_cxt = int_cxt, occ_n_br = n_br }
+ | exprIsTrivial rhs -> True
+ | otherwise -> check_one_occ in_lam int_cxt n_br
- | n_br == 1, NotInsideLam <- in_lam -- One syntactic occurrence
- -> True -- See Note [Post-inline for single-use things]
+ IAmDead -> True -- This happens; for example, the case_bndr during case of
+ -- known constructor: case (a,b) of x { (p,q) -> ... }
+ -- Here x isn't mentioned in the RHS, so we don't want to
+ -- create the (dead) let-binding let x = (a,b) in ...
+ where
+ is_top_lvl = isTopLevel (bindContextLevel bind_cxt)
+ is_demanded = isStrUsedDmd (idDemandInfo bndr)
+ occ_info = idOccInfo old_bndr
+ unfolding = idUnfolding bndr
+ arity = idArity bndr
+-- is_cheap = isCheapUnfolding unfolding
+ uf_opts = seUnfoldingOpts env
+ phase = sePhase env
+ active = isActive phase (idInlineActivation bndr)
+ -- See Note [pre/postInlineUnconditionally in gentle mode]
+ -- Check for code-size blow-up from inlining in multiple places
+ code_dup_ok n_br
+ | n_br == 1 = True -- No duplication
+ | n_br >= 100 = False -- See #23627
+ | is_demanded = False -- Demanded => no allocation (it'll be a case expression
+ -- in the end) so inlining duplicates code but nothing more
+ | otherwise = smallEnoughToInline uf_opts unfolding
+
+ -- See Note [Post-inline for single-use things]
+ check_one_occ NotInsideLam NotInteresting n_br = not is_top_lvl && code_dup_ok n_br
+ check_one_occ NotInsideLam IsInteresting n_br = code_dup_ok n_br
+ check_one_occ IsInsideLam NotInteresting _ = False
+ check_one_occ IsInsideLam IsInteresting n_br = arity > 0 && code_dup_ok n_br
+ -- IsInteresting: inlining inside a lambda only with good reason
+ -- See the notes on int_cxt in preInlineUnconditionally
+ -- arity>0: do not inline data strutures under lambdas, only functions
+
+---------------
+-- A wrong bit of code, left here in case you are tempted to do this
-- | is_unlifted -- Unlifted binding, hence ok-for-spec
-- -> True -- hence cheap to inline probably just a primop
--- -- Not a big deal either way
-- No, this is wrong. {v = p +# q; x = K v}.
-- Don't inline v; it'll just get floated out again. Stupid.
+---------------
- | is_demanded
- -> False -- No allocation (it'll be a case expression in the end)
- -- so inlining duplicates code but nothing more
- | otherwise
- -> work_ok in_lam int_cxt && smallEnoughToInline uf_opts unfolding
- -- Multiple syntactic occurences; but lazy, and small enough to dup
- -- ToDo: consider discount on smallEnoughToInline if int_cxt is true
-
- IAmDead -> True -- This happens; for example, the case_bndr during case of
- -- known constructor: case (a,b) of x { (p,q) -> ... }
- -- Here x isn't mentioned in the RHS, so we don't want to
- -- create the (dead) let-binding let x = (a,b) in ...
-
- _ -> False
-
- where
- work_ok NotInsideLam _ = True
- work_ok IsInsideLam IsInteresting = isCheapUnfolding unfolding
- work_ok IsInsideLam NotInteresting = False
- -- NotInsideLam: outside a lambda, we want to be reasonably aggressive
- -- about inlining into multiple branches of case
+ -- NotInsideLam: outside a lambda, when not at top-level we want to be
+ -- reasonably aggressive about inlining into multiple branches of case
-- e.g. let x = <non-value>
-- in case y of { C1 -> ..x..; C2 -> ..x..; C3 -> ... }
-- Inlining can be a big win if C3 is the hot-spot, even if
-- the uses in C1, C2 are not 'interesting'
-- An example that gets worse if you add int_cxt here is 'clausify'
- -- InsideLam: check for acceptable work duplication, using isCheapUnfoldign
- -- int_cxt to prevent us inlining inside a lambda without some
- -- good reason. See the notes on int_cxt in preInlineUnconditionally
+ -- InsideLam:
-- is_unlifted = isUnliftedType (idType bndr)
- is_demanded = isStrUsedDmd (idDemandInfo bndr)
- occ_info = idOccInfo old_bndr
- unfolding = idUnfolding bndr
- uf_opts = seUnfoldingOpts env
- phase = sePhase env
- active = isActive phase (idInlineActivation bndr)
- -- See Note [pre/postInlineUnconditionally in gentle mode]
{- Note [Inline small things to avoid creating a thunk]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1669,23 +1696,24 @@ where GHC.Driver.CmdLine.$wprocessArgs allocated hugely more.
Note [Post-inline for single-use things]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If we have
-
let x = rhs in ...x...
-
and `x` is used exactly once, and not inside a lambda, then we will usually
preInlineUnconditinally. But we can still get this situation in
postInlineUnconditionally:
-
case K rhs of K x -> ...x....
-
Here we'll use `simplAuxBind` to bind `x` to (the already-simplified) `rhs`;
and `x` is used exactly once. It's beneficial to inline right away; otherwise
we risk creating
-
let x = rhs in ...x...
+which will take another iteration of the Simplifier to eliminate.
-which will take another iteration of the Simplifier to eliminate. We do this in
-two places
+A similar, but less frequent, case is
+ let f = \x.blah in ...(\y. ...(f e)...) ...
+Again `preInlineUnconditionally will usually inline `f`, but it can arise
+via `simplAuxBind` if we have something like
+ (\f \y. ...(f e)..) (\x.blah)
+
+We do unconditional post-inlining in two places:
1. In the full `postInlineUnconditionally` look for the special case
of "one occurrence, not under a lambda", and inline unconditionally then.
@@ -1714,24 +1742,20 @@ Alas!
Note [Top level and postInlineUnconditionally]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We don't do postInlineUnconditionally for top-level things (even for
-ones that are trivial):
+We must take care when considering postInlineUnconditionally for top-level things
- * Doing so will inline top-level error expressions that have been
- carefully floated out by FloatOut. More generally, it might
- replace static allocation with dynamic.
+ * Don't inline top-level error expressions that have been carefully floated
+ out by FloatOut. See Note [Top-level bottoming Ids].
- * Even for trivial expressions there's a problem. Consider
+ * Even for trivial expressions we need to take care: we must not
+ postInlineUnconditionally a top-level ManyOccs binder, even if its
+ RHS is trivial. Consider
{-# RULE "foo" forall (xs::[T]). reverse xs = ruggle xs #-}
blah xs = reverse xs
ruggle = sort
- In one simplifier pass we might fire the rule, getting
+ We must not postInlineUnconditionally `ruggle`, because in the same
+ simplifier pass we might fire the rule, getting
blah xs = ruggle xs
- but in *that* simplifier pass we must not do postInlineUnconditionally
- on 'ruggle' because then we'll have an unbound occurrence of 'ruggle'
-
- If the rhs is trivial it'll be inlined by callSiteInline, and then
- the binding will be dead and discarded by the next use of OccurAnal
* There is less point, because the main goal is to get rid of local
bindings used in multiple case branches.
=====================================
compiler/GHC/Core/Utils.hs
=====================================
@@ -397,10 +397,12 @@ mkTicks :: [CoreTickish] -> CoreExpr -> CoreExpr
mkTicks ticks expr = foldr mkTick expr ticks
isSaturatedConApp :: CoreExpr -> Bool
+-- Also includes literals
isSaturatedConApp e = go e []
where go (App f a) as = go f (a:as)
go (Var fun) args
= isConLikeId fun && idArity fun == valArgCount args
+ go (Lit {}) _ = True
go (Cast f _) as = go f as
go _ _ = False
=====================================
compiler/GHC/Parser/Errors/Types.hs
=====================================
@@ -611,6 +611,7 @@ data LexErr
| LexUnterminatedComment -- ^ Unterminated `{-'
| LexUnterminatedOptions -- ^ Unterminated OPTIONS pragma
| LexUnterminatedQQ -- ^ Unterminated quasiquotation
+ deriving (Show,Eq,Ord)
-- | Errors from the Cmm parser
data CmmParserError
=====================================
compiler/GHC/Parser/String.hs
=====================================
@@ -36,6 +36,7 @@ import GHC.Utils.Panic (panic)
type BufPos = Int
data StringLexError = StringLexError LexErr BufPos
+ deriving (Show, Eq)
lexString :: Int -> StringBuffer -> Either StringLexError String
lexString = lexStringWith processChars processChars
@@ -122,20 +123,49 @@ bufferLocatedChars initialBuf len = go initialBuf
-- -----------------------------------------------------------------------------
-- Lexing phases
+-- | Collapse all string gaps in the given input.
+--
+-- Iterates through the input in `go` until we encounter a backslash. The
+-- @stringchar Alex regex only allows backslashes in two places: escape codes
+-- and string gaps.
+--
+-- * If the next character is a space, it has to be the start of a string gap
+-- AND it must end, since the @gap Alex regex will only match if it ends.
+-- Collapse the gap and continue the main iteration loop.
+--
+-- * Otherwise, this is an escape code. If it's an escape code, there are
+-- ONLY three possibilities (see the @escape Alex regex):
+-- 1. The escape code is "\\"
+-- 2. The escape code is "\^\"
+-- 3. The escape code does not have a backslash, other than the initial
+-- backslash
+--
+-- In the first two possibilities, just skip them and continue the main
+-- iteration loop ("skip" as in "keep in the list as-is"). In the last one,
+-- we can just skip the backslash, then continue the main iteration loop.
+-- the rest of the escape code will be skipped as normal characters in the
+-- string; no need to fully parse a proper escape code.
collapseGaps :: HasChar c => [c] -> [c]
collapseGaps = go
where
go = \case
- c1@(Char '\\') : c2@(Char c) : cs
- -- #25784: string gaps are semantically equivalent to "\&"
+ -- Match the start of a string gap + drop gap
+ -- #25784: string gaps are semantically equivalent to "\&"
+ c1@(Char '\\') : Char c : cs
| is_space c -> c1 : setChar '&' c1 : go (dropGap cs)
- | otherwise -> c1 : c2 : go cs
+ -- Match all possible escape characters that include a backslash
+ c1@(Char '\\') : c2@(Char '\\') : cs
+ -> c1 : c2 : go cs
+ c1@(Char '\\') : c2@(Char '^') : c3@(Char '\\') : cs
+ -> c1 : c2 : c3 : go cs
+ -- Otherwise, just keep looping
c : cs -> c : go cs
[] -> []
dropGap = \case
Char '\\' : cs -> cs
_ : cs -> dropGap cs
+ -- Unreachable since gaps must end; see docstring
[] -> panic "gap unexpectedly ended"
resolveEscapes :: HasChar c => [c] -> Either (c, LexErr) [c]
=====================================
compiler/GHC/Unit/Types.hs
=====================================
@@ -1,5 +1,3 @@
-{-# OPTIONS_GHC -Wno-orphans #-} -- instance Data ModuleName
-
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveTraversable #-}
@@ -117,13 +115,6 @@ data GenModule unit = Module
}
deriving (Eq,Ord,Data,Functor)
--- TODO: should be moved back into Language.Haskell.Syntax.Module.Name
-instance Data ModuleName where
- -- don't traverse?
- toConstr _ = abstractConstr "ModuleName"
- gunfold _ _ = error "gunfold"
- dataTypeOf _ = mkNoRepType "ModuleName"
-
-- | A Module is a pair of a 'Unit' and a 'ModuleName'.
type Module = GenModule Unit
=====================================
compiler/Language/Haskell/Syntax/Module/Name.hs
=====================================
@@ -3,6 +3,7 @@ module Language.Haskell.Syntax.Module.Name where
import Prelude
import Data.Char (isAlphaNum)
+import Data.Data
import Control.DeepSeq
import qualified Text.ParserCombinators.ReadP as Parse
import System.FilePath
@@ -12,6 +13,14 @@ import GHC.Data.FastString
-- | A ModuleName is essentially a simple string, e.g. @Data.List@.
newtype ModuleName = ModuleName FastString deriving (Show, Eq)
+instance Data ModuleName where
+ -- don't traverse?
+ toConstr x = constr
+ where
+ constr = mkConstr (dataTypeOf x) "{abstract:ModuleName}" [] Prefix
+ gunfold _ _ = error "gunfold"
+ dataTypeOf _ = mkNoRepType "ModuleName"
+
instance Ord ModuleName where
nm1 `compare` nm2 = stableModuleNameCmp nm1 nm2
=====================================
hadrian/README.md
=====================================
@@ -226,8 +226,8 @@ tested in CI. If you use an untested flavour such as "Quick" then you run the
risk that not all tests will pass. In particular you can rely on the `validate`
and `perf` flavours being tested but no others.
-`build selftest` runs tests of the build system. The current test coverage
-is close to zero (see [#197][test-issue]).
+`build selftest` (no longer enabled by default) runs tests of the build system.
+The current test coverage is close to zero (see [#197][test-issue]).
#### Running linters
=====================================
hadrian/hadrian.cabal
=====================================
@@ -27,7 +27,7 @@ flag threaded
-- See also #21913
flag selftest
manual: True
- default: True
+ default: False
description: Enables the hadrian selftest rules which require
QuickCheck. Disabling it thus saves on a few dependencies
which can be problematic when bootstrapping.
=====================================
libraries/ghc-internal/src/GHC/Internal/Base.hs
=====================================
@@ -1809,7 +1809,12 @@ build g = g (:) []
augment :: forall a. (forall b. (a->b->b) -> b -> b) -> [a] -> [a]
{-# INLINE [1] augment #-}
-augment g xs = g (:) xs
+-- Give it one argument so that it inlines with one arg
+-- But (crucially) the body is a lambda so that `g` is visibly applied
+-- to two args, and hence we know that in a call
+-- augment (\c n. blah)
+-- both c and n are OneShot
+augment g = \xs -> g (:) xs
{-# RULES
"fold/build" forall k z (g::forall b. (a->b->b) -> b -> b) .
@@ -1975,7 +1980,7 @@ The rules for map work like this.
"++/literal_utf8" forall x. (++) (unpackCStringUtf8# x) = unpackAppendCStringUtf8# x #-}
{-# RULES
-"++" [~1] forall xs ys. xs ++ ys = augment (\c n -> foldr c n xs) ys
+"++" [~1] forall xs. (++) xs = augment (\c n -> foldr c n xs)
#-}
=====================================
libraries/ghc-internal/src/GHC/Internal/Float.hs
=====================================
@@ -5,6 +5,7 @@
, MagicHash
, UnboxedTuples
, UnliftedFFITypes
+ , TypeApplications
#-}
{-# LANGUAGE CApiFFI #-}
-- We believe we could deorphan this module, by moving lots of things
@@ -1696,6 +1697,16 @@ showSignedFloat showPos p x
= showParen (p > 6) (showChar '-' . showPos (-x))
| otherwise = showPos x
+
+-- Speicialise showSignedFloat for (a) the type and (b) the argument function
+-- The particularly targets are the calls in `instance Show Float` and
+-- `instance Show Double`
+-- Specialising for both (a) and (b) is obviously more efficient; and if you
+-- don't you find that the `x` argument is strict, but boxed, and that can cause
+-- functions calling showSignedFloat to have box their argument.
+{-# SPECIALISE showSignedFloat @Float showFloat #-}
+{-# SPECIALISE showSignedFloat @Double showFloat #-}
+
{-
We need to prevent over/underflow of the exponent in encodeFloat when
called from scaleFloat, hence we clamp the scaling parameter.
=====================================
m4/fp_setup_windows_toolchain.m4
=====================================
@@ -17,12 +17,13 @@ AC_DEFUN([FP_INSTALL_WINDOWS_TOOLCHAIN],[
else
action="download"
fi
- $PYTHON mk/get-win32-tarballs.py $action $mingw_arch > missing-win32-tarballs
+ $PYTHON mk/get-win32-tarballs.py $action $mingw_arch
case $? in
0)
rm missing-win32-tarballs
;;
2)
+ $PYTHON mk/get-win32-tarballs.py list $mingw_arch > missing-win32-tarballs
echo
echo "Error:"
echo "Needed msys2 tarballs are missing. You have a few options to get them,"
=====================================
testsuite/tests/arityanal/should_compile/T18793.stderr
=====================================
@@ -1,54 +1,44 @@
==================== Tidy Core ====================
-Result size of Tidy Core = {terms: 64, types: 40, coercions: 0, joins: 0/0}
+Result size of Tidy Core = {terms: 60, types: 34, coercions: 0, joins: 0/0}
-- RHS size: {terms: 17, types: 7, coercions: 0, joins: 0/0}
stuff [InlPrag=NOINLINE] :: Int -> [Int]
[GblId, Arity=1, Str=<1L>, Unf=OtherCon []]
-stuff = \ (i :: Int) -> case i of i1 { GHC.Types.I# ipv -> GHC.Types.: @Int i1 (GHC.Types.: @Int (GHC.Types.I# (GHC.Prim.+# ipv 1#)) (GHC.Types.: @Int (GHC.Types.I# (GHC.Prim.+# ipv 2#)) (GHC.Types.[] @Int))) }
+stuff = \ (i :: Int) -> case i of i1 { GHC.Internal.Types.I# ipv -> GHC.Internal.Types.: @Int i1 (GHC.Internal.Types.: @Int (GHC.Internal.Types.I# (GHC.Internal.Prim.+# ipv 1#)) (GHC.Internal.Types.: @Int (GHC.Internal.Types.I# (GHC.Internal.Prim.+# ipv 2#)) (GHC.Internal.Types.[] @Int))) }
Rec {
-- RHS size: {terms: 23, types: 11, coercions: 0, joins: 0/0}
-T18793.$wgo1 [InlPrag=[2], Occ=LoopBreaker] :: [Int] -> GHC.Prim.Int# -> GHC.Prim.Int#
+T18793.$wgo1 [InlPrag=[2], Occ=LoopBreaker] :: [Int] -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int#
[GblId[StrictWorker([!])], Arity=2, Str=<1L><L>, Unf=OtherCon []]
T18793.$wgo1
- = \ (ds :: [Int]) (ww :: GHC.Prim.Int#) ->
+ = \ (ds :: [Int]) (ww :: GHC.Internal.Prim.Int#) ->
case ds of {
[] -> ww;
: y ys ->
- case y of { GHC.Types.I# x ->
- case GHC.Prim.># x 42# of {
+ case y of { GHC.Internal.Types.I# x ->
+ case GHC.Internal.Prim.># x 42# of {
__DEFAULT -> T18793.$wgo1 ys ww;
- 1# -> T18793.$wgo1 ys (GHC.Prim.negateInt# ww)
+ 1# -> T18793.$wgo1 ys (GHC.Internal.Prim.negateInt# ww)
}
}
}
end Rec }
--- RHS size: {terms: 12, types: 6, coercions: 0, joins: 0/0}
-T18793.f_go1 [InlPrag=[2]] :: [Int] -> Int -> Int
-[GblId,
- Arity=2,
- Str=<1L><1!P(L)>,
- Cpr=1,
- Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
- Tmpl= \ (ds [Occ=Once1] :: [Int]) (eta [Occ=Once1!, OS=OneShot] :: Int) -> case eta of { GHC.Types.I# ww [Occ=Once1] -> case T18793.$wgo1 ds ww of ww1 [Occ=Once1] { __DEFAULT -> GHC.Types.I# ww1 } }}]
-T18793.f_go1 = \ (ds :: [Int]) (eta [OS=OneShot] :: Int) -> case eta of { GHC.Types.I# ww -> case T18793.$wgo1 ds ww of ww1 { __DEFAULT -> GHC.Types.I# ww1 } }
-
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
T18793.f2 :: Int
[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
-T18793.f2 = GHC.Types.I# 1#
+T18793.f2 = GHC.Internal.Types.I# 1#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
T18793.f1 :: [Int]
[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}]
T18793.f1 = stuff T18793.f2
--- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
+-- RHS size: {terms: 11, types: 4, coercions: 0, joins: 0/0}
f :: Int -> Int
-[GblId, Arity=1, Str=<1!P(L)>, Cpr=1, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 20 60}]
-f = T18793.f_go1 T18793.f1
+[GblId, Arity=1, Str=<1!P(L)>, Cpr=1, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [20] 60 10}]
+f = \ (eta [OS=OneShot] :: Int) -> case eta of { GHC.Internal.Types.I# ww -> case T18793.$wgo1 T18793.f1 ww of ww1 { __DEFAULT -> GHC.Internal.Types.I# ww1 } }
=====================================
testsuite/tests/driver/inline-check.stderr
=====================================
@@ -17,7 +17,6 @@ Inactive unfolding: foo1
Inactive unfolding: foo1
Inactive unfolding: foo1
Inactive unfolding: foo1
-Inactive unfolding: foo1
Considering inlining: foo
arg infos []
interesting continuation RhsCtxt(NonRecursive)
=====================================
testsuite/tests/ghci.debugger/scripts/break011.stdout
=====================================
@@ -29,9 +29,9 @@ HasCallStack backtrace:
error, called at Test7.hs:2:18 in main:Main
Stopped in <exception thrown>, <unknown>
-_exception :: e = SomeException (ErrorCall "foo")
+_exception :: e = _
Stopped in <exception thrown>, <unknown>
-_exception :: e = SomeException (ErrorCall "foo")
+_exception :: e = _
*** Exception: foo
HasCallStack backtrace:
=====================================
testsuite/tests/ghci.debugger/scripts/break024.stdout
=====================================
@@ -17,9 +17,7 @@ _exception = SomeException
Nothing GHC.Internal.IO.Exception.UserError [] "error" Nothing
Nothing)
Stopped in <exception thrown>, <unknown>
-_exception :: e = SomeException
- (GHC.Internal.IO.Exception.IOError
- Nothing GHC.Internal.IO.Exception.UserError ....)
+_exception :: e = _
Stopped in <exception thrown>, <unknown>
_exception :: e = _
_exception = SomeException
=====================================
testsuite/tests/parser/should_run/T25937.hs
=====================================
@@ -0,0 +1,2 @@
+main :: IO ()
+main = print "\^\ "
=====================================
testsuite/tests/parser/should_run/T25937.stdout
=====================================
@@ -0,0 +1 @@
+"\FS "
=====================================
testsuite/tests/parser/should_run/all.T
=====================================
@@ -1,3 +1,8 @@
+test('parser_unit_tests',
+ normal,
+ compile_and_run,
+ ['-package ghc'])
+
test('readRun001', normal, compile_and_run, [''])
test('readRun002', normal, compile_and_run, [''])
test('readRun003', normal, compile_and_run, [''])
@@ -21,6 +26,7 @@ test('RecordDotSyntax3', [extra_files(['RecordDotSyntaxA.hs'])], multimod_compil
test('RecordDotSyntax4', [extra_files(['RecordDotSyntaxA.hs'])], multimod_compile_and_run, ['RecordDotSyntax4', ''])
test('RecordDotSyntax5', normal, compile_and_run, [''])
test('ListTuplePunsConstraints', extra_files(['ListTuplePunsConstraints.hs']), ghci_script, ['ListTuplePunsConstraints.script'])
+test('T25937', normal, compile_and_run, [''])
# Multiline strings
test('MultilineStrings', normal, compile_and_run, [''])
=====================================
testsuite/tests/parser/should_run/parser_unit_tests.hs
=====================================
@@ -0,0 +1,82 @@
+import GHC.Data.StringBuffer (stringToStringBuffer)
+import qualified GHC.Data.StringBuffer as StringBuffer (StringBuffer (..))
+import GHC.Parser.String (lexString, lexMultilineString)
+
+import qualified Control.Exception as E
+import Control.Monad (forM_, unless)
+
+main :: IO ()
+main = do
+ forM_ tests $ \(testName, test) -> do
+ result <- E.try test
+ case result of
+ Right () -> pure ()
+ Left (e :: E.SomeException)
+ | Just e' <- E.asyncExceptionFromException e -> do
+ E.throwIO (e' :: E.AsyncException)
+ | otherwise -> do
+ putStrLn $ ">>> FAIL: " ++ testName
+ putStrLn $ E.displayException e
+
+{----- Test infrastructure -----}
+
+data TestFailure = TestFailure String
+ deriving (Show)
+
+instance E.Exception TestFailure where
+ displayException (TestFailure msg) = "Test failure:\n" ++ msg
+
+testFailure :: String -> IO a
+testFailure = E.throwIO . TestFailure
+
+shouldBe :: (Eq a, Show a) => a -> a -> IO ()
+shouldBe actual expected =
+ unless (actual == expected) $
+ testFailure $
+ "Got: " ++ show actual ++ "\n" ++
+ "Expected: " ++ show expected
+
+type TestCase = (String, IO ())
+
+testCase :: String -> IO () -> TestCase
+testCase = (,)
+
+{----- Tests -----}
+
+tests :: [TestCase]
+tests = concat
+ [ stringTests
+ ]
+
+-- | Unit tests for GHC.Parser.String
+stringTests :: [TestCase]
+stringTests = concat
+ [ escapedBackslashTests
+ ]
+ where
+ withBuf f s = let buf = stringToStringBuffer s in f (StringBuffer.len buf) buf
+
+ -- Test all situations where backslashes can appear in escape characters (#25937)
+ escapedBackslashTests =
+ [ testCase label $ do
+ withBuf lexStr input `shouldBe` Right output
+ | (lexLabel, lexStr) <- [("strings", lexString), ("multiline strings", lexMultilineString)]
+ , (label, input, output) <-
+ [ ( "escaped backslashes in " ++ lexLabel ++ " not mistaken for string gaps"
+ , [' ', '\\', '\\', ' ', '\\', '\\', ' ']
+ , " \\ \\ "
+ )
+ , ( "escaped \\FS in " ++ lexLabel ++ " not mistaken for beginning of string gap"
+ , ['\\', '^', '\\']
+ , "\FS"
+ )
+ , ( "escaped \\FS in " ++ lexLabel ++ " not mistaken for unterminated string gap"
+ , ['\\', '^', '\\', ' ']
+ , "\FS "
+ )
+ , ( "escaped \\FS in " ++ lexLabel ++ " does not collapse mistaken string gap"
+ , ['\\', '^', '\\', ' ', '\\', 'n']
+ , "\FS \n"
+ )
+ ]
+ ]
=====================================
testsuite/tests/simplCore/should_run/simplrun009.hs
=====================================
@@ -6,7 +6,10 @@
-- It produces a nested unfold that should look something
-- like the code below. Note the 'lvl1_shW'. It is BAD
-- if this is a lambda instead; you get a lot more allocation
--- See Note [Saving allocation] in GHC.Core.Opt.SetLevels
+--
+-- LATER (2025): But in the end it seems better NOT to float lambdas,
+-- unless they go to top level.
+-- See (SW2) in Note [Saving work] in GHC.Core.Opt.SetLevels
{-
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e35271b8eba4e5f056014f2cebc2b7…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e35271b8eba4e5f056014f2cebc2b7…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/marge_bot_batch_merge_job] Suppress unused do-binding if discarded variable is Any or ZonkAny.
by Marge Bot (@marge-bot) 01 May '25
by Marge Bot (@marge-bot) 01 May '25
01 May '25
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
d3209b4e by Javran Cheng at 2025-05-01T09:33:33-04:00
Suppress unused do-binding if discarded variable is Any or ZonkAny.
Consider example (#25895):
> do { forever (return ()); blah }
where `forever :: forall a b. IO a -> IO b`.
Nothing constrains `b`, so it will be instantiates with `Any` or
`ZonkAny`.
But we certainly don't want to complain about a discarded do-binding.
Fixes #25895
- - - - -
4 changed files:
- compiler/GHC/Builtin/Types.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/Tc/Utils/TcType.hs
- testsuite/tests/printer/T17697.stderr
Changes:
=====================================
compiler/GHC/Builtin/Types.hs
=====================================
@@ -510,6 +510,17 @@ Wrinkles:
See examples in ghc-prim:GHC.Types
+(Any8) Warning about unused bindings of type `Any` and `ZonkAny` are suppressed,
+ following the same rationale of supressing warning about the unit type.
+
+ For example, consider (#25895):
+
+ do { forever (return ()); blah }
+
+ where forever :: forall a b. IO a -> IO b
+ Nothing constrains `b`, so it will be instantiates with `Any` or `ZonkAny`.
+ But we certainly don't want to complain about a discarded do-binding.
+
The Any tycon used to be quite magic, but we have since been able to
implement it merely with an empty kind polymorphic type family. See #10886 for a
bit of history.
=====================================
compiler/GHC/HsToCore/Expr.hs
=====================================
@@ -1243,9 +1243,13 @@ warnDiscardedDoBindings rhs m_ty elt_ty
; when (warn_unused || warn_wrong) $
do { fam_inst_envs <- dsGetFamInstEnvs
; let norm_elt_ty = topNormaliseType fam_inst_envs elt_ty
-
- -- Warn about discarding non-() things in 'monadic' binding
- ; if warn_unused && not (isUnitTy norm_elt_ty)
+ supressible_ty =
+ isUnitTy norm_elt_ty || isAnyTy norm_elt_ty || isZonkAnyTy norm_elt_ty
+ -- Warn about discarding things in 'monadic' binding,
+ -- however few types are excluded:
+ -- * Unit type `()`
+ -- * `ZonkAny` or `Any` type see (Any8) of Note [Any types]
+ ; if warn_unused && not supressible_ty
then diagnosticDs (DsUnusedDoBind rhs elt_ty)
else
=====================================
compiler/GHC/Tc/Utils/TcType.hs
=====================================
@@ -88,7 +88,7 @@ module GHC.Tc.Utils.TcType (
isSigmaTy, isRhoTy, isRhoExpTy, isOverloadedTy,
isFloatingPrimTy, isDoubleTy, isFloatTy, isIntTy, isWordTy, isStringTy,
isIntegerTy, isNaturalTy,
- isBoolTy, isUnitTy, isCharTy,
+ isBoolTy, isUnitTy, isAnyTy, isZonkAnyTy, isCharTy,
isTauTy, isTauTyCon, tcIsTyVarTy,
isPredTy, isTyVarClassPred,
checkValidClsArgs, hasTyVarHead,
@@ -2006,7 +2006,7 @@ isFloatTy, isDoubleTy,
isFloatPrimTy, isDoublePrimTy,
isIntegerTy, isNaturalTy,
isIntTy, isWordTy, isBoolTy,
- isUnitTy, isCharTy :: Type -> Bool
+ isUnitTy, isAnyTy, isZonkAnyTy, isCharTy :: Type -> Bool
isFloatTy = is_tc floatTyConKey
isDoubleTy = is_tc doubleTyConKey
isFloatPrimTy = is_tc floatPrimTyConKey
@@ -2017,6 +2017,8 @@ isIntTy = is_tc intTyConKey
isWordTy = is_tc wordTyConKey
isBoolTy = is_tc boolTyConKey
isUnitTy = is_tc unitTyConKey
+isAnyTy = is_tc anyTyConKey
+isZonkAnyTy = is_tc zonkAnyTyConKey
isCharTy = is_tc charTyConKey
-- | Check whether the type is of the form @Any :: k@,
=====================================
testsuite/tests/printer/T17697.stderr
=====================================
@@ -1,8 +1,2 @@
T17697.hs:6:5: warning: [GHC-88464] [-Wdeferred-out-of-scope-variables (in -Wdefault)]
Variable not in scope: threadDelay :: t0 -> IO a0
-
-T17697.hs:6:5: warning: [GHC-81995] [-Wunused-do-bind (in -Wall)]
- A do-notation statement discarded a result of type
- ‘GHC.Internal.Types.ZonkAny 1’
- Suggested fix: Suppress this warning by saying ‘_ <- threadDelay 1’
-
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d3209b4ec12509805c27920ed682bfb…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/d3209b4ec12509805c27920ed682bfb…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

01 May '25
Zubin pushed to branch wip/9.10.2-final at Glasgow Haskell Compiler / GHC
Commits:
c9de16b5 by Zubin Duggal at 2025-05-01T18:48:01+05:30
release-notes: fix flag references
- - - - -
1 changed file:
- docs/users_guide/9.10.2-notes.rst
Changes:
=====================================
docs/users_guide/9.10.2-notes.rst
=====================================
@@ -149,7 +149,7 @@ Runtime system
- Reduce fragmentation incurred by the non-moving GC's segment allocator. In one application this reduced resident
set size by 26%. See :ghc-ticket:`24150`.
-- Emit warning when :ghc-flag:`-M` is less than :ghc-flag:`-H`.
+- Emit warning when :rts-flag:`-M ⟨size⟩` is less than :rts-flag:`-H [⟨size⟩]`.
- Fix a bug ((:ghc-ticket:`24672`)) causing programms on FreeBSD to occasionally terminate with the error:
``internal error: Ticker: read(timerfd) failed with Operation not supported and returned -1``
@@ -178,7 +178,7 @@ Build system and packaging
(From https://git.savannah.gnu.org/cgit/config.git/)
- GHC now distinguishes more between the Cmm and C preprocessor. The new flags
- :ghc-flag:`-pgmCmmP` and :ghc-flag:`-optCmmP` can be used to control
+ :ghc-flag:`-pgmCmmP ⟨cmd⟩` and :ghc-flag:`-optCmmP ⟨option⟩` can be used to control
the Cmm preprocessor. C preprocessor flags will still be passed to the Cmm
preprocessor, expect for :ghc-flag:`-g` flags which have special handling. Fixes (:ghc-ticket:`24474`)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c9de16b57adcb6810d059ebd1c72d97…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c9de16b57adcb6810d059ebd1c72d97…
You're receiving this email because of your account on gitlab.haskell.org.
1
0

[Git][ghc/ghc][wip/T23109a] 3 commits: Accept some error message changes
by Simon Peyton Jones (@simonpj) 01 May '25
by Simon Peyton Jones (@simonpj) 01 May '25
01 May '25
Simon Peyton Jones pushed to branch wip/T23109a at Glasgow Haskell Compiler / GHC
Commits:
bcd2de99 by Simon Peyton Jones at 2025-05-01T13:56:17+01:00
Accept some error message changes
* break011, break024: GHCi debugger output. Not quite so good but
@alt-romes says it's fine. Very delicate tests, depend on fluky
inlining.
* inline-check: an improvement! After this patch we do one fewer
iterations of the Simplifier.
- - - - -
5b053156 by Simon Peyton Jones at 2025-05-01T13:56:30+01:00
Accept diff
* T18793: good: code is simpler and better
- - - - -
e35271b8 by Simon Peyton Jones at 2025-05-01T13:56:42+01:00
Experminental and subtle change in OccAnal
Concerns handling of join points and interaction with exitification
- - - - -
5 changed files:
- compiler/GHC/Core/Opt/OccurAnal.hs
- testsuite/tests/arityanal/should_compile/T18793.stderr
- testsuite/tests/driver/inline-check.stderr
- testsuite/tests/ghci.debugger/scripts/break011.stdout
- testsuite/tests/ghci.debugger/scripts/break024.stdout
Changes:
=====================================
compiler/GHC/Core/Opt/OccurAnal.hs
=====================================
@@ -3797,8 +3797,9 @@ lookupOccInfoByUnique (UD { ud_env = env
, occ_int_cxt = int_cxt
, occ_tail = mk_tail_info tail_info }
where
- in_lam | uniq `elemVarEnvByKey` z_in_lam = IsInsideLam
- | otherwise = NotInsideLam
+ in_lam | uniq `elemVarEnvByKey` z_in_lam
+ , n_br > 0 = IsInsideLam
+ | otherwise = NotInsideLam
Just (ManyOccL tail_info) -> ManyOccs { occ_tail = mk_tail_info tail_info }
where
=====================================
testsuite/tests/arityanal/should_compile/T18793.stderr
=====================================
@@ -1,54 +1,44 @@
==================== Tidy Core ====================
-Result size of Tidy Core = {terms: 64, types: 40, coercions: 0, joins: 0/0}
+Result size of Tidy Core = {terms: 60, types: 34, coercions: 0, joins: 0/0}
-- RHS size: {terms: 17, types: 7, coercions: 0, joins: 0/0}
stuff [InlPrag=NOINLINE] :: Int -> [Int]
[GblId, Arity=1, Str=<1L>, Unf=OtherCon []]
-stuff = \ (i :: Int) -> case i of i1 { GHC.Types.I# ipv -> GHC.Types.: @Int i1 (GHC.Types.: @Int (GHC.Types.I# (GHC.Prim.+# ipv 1#)) (GHC.Types.: @Int (GHC.Types.I# (GHC.Prim.+# ipv 2#)) (GHC.Types.[] @Int))) }
+stuff = \ (i :: Int) -> case i of i1 { GHC.Internal.Types.I# ipv -> GHC.Internal.Types.: @Int i1 (GHC.Internal.Types.: @Int (GHC.Internal.Types.I# (GHC.Internal.Prim.+# ipv 1#)) (GHC.Internal.Types.: @Int (GHC.Internal.Types.I# (GHC.Internal.Prim.+# ipv 2#)) (GHC.Internal.Types.[] @Int))) }
Rec {
-- RHS size: {terms: 23, types: 11, coercions: 0, joins: 0/0}
-T18793.$wgo1 [InlPrag=[2], Occ=LoopBreaker] :: [Int] -> GHC.Prim.Int# -> GHC.Prim.Int#
+T18793.$wgo1 [InlPrag=[2], Occ=LoopBreaker] :: [Int] -> GHC.Internal.Prim.Int# -> GHC.Internal.Prim.Int#
[GblId[StrictWorker([!])], Arity=2, Str=<1L><L>, Unf=OtherCon []]
T18793.$wgo1
- = \ (ds :: [Int]) (ww :: GHC.Prim.Int#) ->
+ = \ (ds :: [Int]) (ww :: GHC.Internal.Prim.Int#) ->
case ds of {
[] -> ww;
: y ys ->
- case y of { GHC.Types.I# x ->
- case GHC.Prim.># x 42# of {
+ case y of { GHC.Internal.Types.I# x ->
+ case GHC.Internal.Prim.># x 42# of {
__DEFAULT -> T18793.$wgo1 ys ww;
- 1# -> T18793.$wgo1 ys (GHC.Prim.negateInt# ww)
+ 1# -> T18793.$wgo1 ys (GHC.Internal.Prim.negateInt# ww)
}
}
}
end Rec }
--- RHS size: {terms: 12, types: 6, coercions: 0, joins: 0/0}
-T18793.f_go1 [InlPrag=[2]] :: [Int] -> Int -> Int
-[GblId,
- Arity=2,
- Str=<1L><1!P(L)>,
- Cpr=1,
- Unf=Unf{Src=InlineStable, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=ALWAYS_IF(arity=2,unsat_ok=True,boring_ok=False)
- Tmpl= \ (ds [Occ=Once1] :: [Int]) (eta [Occ=Once1!, OS=OneShot] :: Int) -> case eta of { GHC.Types.I# ww [Occ=Once1] -> case T18793.$wgo1 ds ww of ww1 [Occ=Once1] { __DEFAULT -> GHC.Types.I# ww1 } }}]
-T18793.f_go1 = \ (ds :: [Int]) (eta [OS=OneShot] :: Int) -> case eta of { GHC.Types.I# ww -> case T18793.$wgo1 ds ww of ww1 { __DEFAULT -> GHC.Types.I# ww1 } }
-
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
T18793.f2 :: Int
[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 10}]
-T18793.f2 = GHC.Types.I# 1#
+T18793.f2 = GHC.Internal.Types.I# 1#
-- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
T18793.f1 :: [Int]
[GblId, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False, WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 20 0}]
T18793.f1 = stuff T18793.f2
--- RHS size: {terms: 2, types: 0, coercions: 0, joins: 0/0}
+-- RHS size: {terms: 11, types: 4, coercions: 0, joins: 0/0}
f :: Int -> Int
-[GblId, Arity=1, Str=<1!P(L)>, Cpr=1, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 20 60}]
-f = T18793.f_go1 T18793.f1
+[GblId, Arity=1, Str=<1!P(L)>, Cpr=1, Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True, WorkFree=True, Expandable=True, Guidance=IF_ARGS [20] 60 10}]
+f = \ (eta [OS=OneShot] :: Int) -> case eta of { GHC.Internal.Types.I# ww -> case T18793.$wgo1 T18793.f1 ww of ww1 { __DEFAULT -> GHC.Internal.Types.I# ww1 } }
=====================================
testsuite/tests/driver/inline-check.stderr
=====================================
@@ -17,7 +17,6 @@ Inactive unfolding: foo1
Inactive unfolding: foo1
Inactive unfolding: foo1
Inactive unfolding: foo1
-Inactive unfolding: foo1
Considering inlining: foo
arg infos []
interesting continuation RhsCtxt(NonRecursive)
=====================================
testsuite/tests/ghci.debugger/scripts/break011.stdout
=====================================
@@ -29,9 +29,9 @@ HasCallStack backtrace:
error, called at Test7.hs:2:18 in main:Main
Stopped in <exception thrown>, <unknown>
-_exception :: e = SomeException (ErrorCall "foo")
+_exception :: e = _
Stopped in <exception thrown>, <unknown>
-_exception :: e = SomeException (ErrorCall "foo")
+_exception :: e = _
*** Exception: foo
HasCallStack backtrace:
=====================================
testsuite/tests/ghci.debugger/scripts/break024.stdout
=====================================
@@ -17,9 +17,7 @@ _exception = SomeException
Nothing GHC.Internal.IO.Exception.UserError [] "error" Nothing
Nothing)
Stopped in <exception thrown>, <unknown>
-_exception :: e = SomeException
- (GHC.Internal.IO.Exception.IOError
- Nothing GHC.Internal.IO.Exception.UserError ....)
+_exception :: e = _
Stopped in <exception thrown>, <unknown>
_exception :: e = _
_exception = SomeException
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/680f1b6076ef87c2a7b6f0ff5fe02d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/680f1b6076ef87c2a7b6f0ff5fe02d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
Simon Peyton Jones pushed to branch wip/T26004 at Glasgow Haskell Compiler / GHC
Commits:
4a070bbb by Simon Peyton Jones at 2025-05-01T12:21:50+01:00
One more wibble
- - - - -
1 changed file:
- compiler/GHC/Tc/Solver.hs
Changes:
=====================================
compiler/GHC/Tc/Solver.hs
=====================================
@@ -1476,9 +1476,8 @@ decideAndPromoteTyVars top_lvl rhs_tclvl infer_mode name_taus psigs wanted
--------------------------------------------------------------------
-- Step 4 of Note [decideAndPromoteTyVars]
-- Use closeWrtFunDeps to find any other variables that are determined by mono_tvs
- -- ToDo: can_quant, not (no_quant ++ can_quant); #26004
- add_determined tvs = closeWrtFunDeps can_quant tvs
- `delVarSetList` psig_qtvs
+ add_determined tvs preds = closeWrtFunDeps preds tvs
+ `delVarSetList` psig_qtvs
-- Why delVarSetList psig_qtvs?
-- If the user has explicitly asked for quantification, then that
-- request "wins" over the MR.
@@ -1487,8 +1486,8 @@ decideAndPromoteTyVars top_lvl rhs_tclvl infer_mode name_taus psigs wanted
-- (i.e. says "no" to isQuantifiableTv)? That's OK: explanation
-- in Step 2 of Note [Deciding quantification].
- mono_tvs_with_mr_det = add_determined mono_tvs_with_mr
- mono_tvs_without_mr_det = add_determined mono_tvs_without_mr
+ mono_tvs_with_mr_det = add_determined mono_tvs_with_mr post_mr_quant
+ mono_tvs_without_mr_det = add_determined mono_tvs_without_mr can_quant
--------------------------------------------------------------------
-- Step 5 of Note [decideAndPromoteTyVars]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4a070bbb4fd3923da3bdf86b77d3dab…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4a070bbb4fd3923da3bdf86b77d3dab…
You're receiving this email because of your account on gitlab.haskell.org.
1
0