[Git][ghc/ghc][wip/az/exactprint-annotation-rationalisation] 3 commits: WIP on removing NoEpAnn. Likely abandon
by Alan Zimmerman (@alanz) 21 Jul '26
by Alan Zimmerman (@alanz) 21 Jul '26
21 Jul '26
Alan Zimmerman pushed to branch wip/az/exactprint-annotation-rationalisation at Glasgow Haskell Compiler / GHC
Commits:
d981d339 by Alan Zimmerman at 2026-07-21T19:24:01+01:00
WIP on removing NoEpAnn. Likely abandon
- - - - -
79c819d5 by Alan Zimmerman at 2026-07-21T19:24:01+01:00
EPA: Add an overview doc for exact printing
- - - - -
cd5e0673 by Simon Peyton Jones at 2026-07-21T19:24:01+01:00
Added an intro section
- - - - -
6 changed files:
- + ExactPrint.md
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/Language/Haskell/Syntax/Expr.hs
Changes:
=====================================
ExactPrint.md
=====================================
@@ -0,0 +1,553 @@
+# GHC Exact Print Annotations — Technical Overview
+
+## Motivation
+
+A central goal of Haskell tooling — refactoring engines, formatters, language servers, code
+generators — is to make targeted edits to a Haskell source file and then emit the result with
+_only the intended changes_ applied. A naive approach of pretty-printing the parsed AST loses
+all original layout, comments, and stylistic choices, producing diffs that are far larger than
+the semantic change.
+
+GHC's **Exact Print Annotation (EPA)** subsystem solves this by embedding enough positional
+information directly into every AST node to allow the tree to be reprinted _exactly_ as the
+original source, byte-for-byte (modulo tab expansion). When a tool modifies the AST it adjusts
+only the annotations it needs to change; all surrounding nodes reprint themselves unchanged.
+
+## Background: the syntax tree
+
+The AST of the source program is represented using the data types defined in `Language.Haskell.Syntax.*`.
+This data type uses the "Trees That Grow (TTG)" plan;
+see [Implementing trees that grow](https://gitlab.haskell.org/ghc/ghc/-/wikis/implementing-trees-that-gr…
+
+For example, in (GHC-independent) `Language.Haskell.Syntax.Expr`:
+```
+data HsExpr p
+ = ... many constructors including ...
+ | HsLet (XLet p)
+ (HsLocalBinds p)
+ (LHsExpr p)
+
+type family XLet p
+type LHsExpr p = XRec p (HsExpr p)
+
+```
+Note that
+* The `(XLet p)` field is the *extension field* of the `HsLet` data constructor,
+ where `XLet` is a type family.
+* Almost every node is wrapped in an `XRec`, another type family. That makes it easy
+ for clients to attach arbitrary information to each node.
+
+GHC specialises this data a type in `GHC.Hs.*`, as follows:
+```
+data Pass = Parsed | Renamed | Typechecked
+
+data GhcPass (c :: Pass) where
+ GhcPs :: GhcPass 'Parsed
+ GhcRn :: GhcPass 'Renamed
+ GhcTc :: GhcPass 'Typechecked
+
+type family XRec p a = r | r -> a
+type instance XRec (GhcPass p) t = XRecGhc t
+
+-- (XRecGhc tree) wraps `tree` in a GHC-specific,
+-- but pass-independent, source location
+type XRecGhc t = GenLocated (Anno t) t
+
+data GenLocated l e = L l e
+type family Anno t
+```
+So, via `XRec`, every node `e :: t` in the GHC-specific version of HsSyn is wrapped in
+a `L ann e`, where `ann :: Anno t` is the annotation on the node.
+
+Notice that there are two places we can hang information:
+* (EXT) **Constructor-specific punctuation**: the extension field of each data constructor
+ can contain information that is specific to that constructor. Example: the location
+ of the keywords `let` and `in` for the `HsLet` construct.
+
+* (XREC) **Entire-node information**: the `Anno t` field that wraps almost every node in the
+ syntax tree can contain information that is needed for *every* node. Classic example:
+ the `SrcSpan` of the node.
+
+**NOTE**: currently there is information in (XREC) that more properly belongs in (EXT).
+A refactoring project is under way to put this right.
+
+
+## File layout
+
+The subsystem lives primarily in `utils/check-exact/` and is exposed through three main layers:
+
+| Layer | Key operation | Purpose |
+|---|---|---|
+| **Parser** | `getCommentsFor` / `getPriorCommentsFor` | Attaches comments to AST nodes |
+| **Printer** | `exactPrint` / `makeDeltaAst` | Reprints the AST; converts absolute spans to relative deltas |
+| **Transform** | `Transform` monad | Edits the AST while keeping annotations consistent |
+
+---
+
+## Core Concepts
+
+### Positions: Absolute and Relative
+
+The parser records every token's position as an **absolute** source span (file, line, column).
+Before reprinting a modified AST the printer converts these to **relative** (delta) form.
+
+```
+EpaLocation
+ ├─ EpaSpan (absolute) — original (line, col) span from the parser
+ └─ EpaDelta (relative) — DeltaPos + retained original span + leading comments
+```
+
+A `DeltaPos` encodes a position as an offset from a _reference point_:
+
+```
+DeltaPos
+ ├─ SameLine col — rightward gap from the end of the preceding token; col ≥ 0
+ └─ DifferentLine lines col
+ — lines below the preceding token;
+ col is a SIGNED offset from the enclosing layout block's
+ left margin (layout_lhs + col = absolute column)
+```
+
+The different reference points for the two constructors are deliberate and are what makes
+layout-preserving moves possible (see _Splice Invariance_ below).
+
+---
+
+## Invariants
+
+### 1. Every Node Is Self-Contained
+
+Each located AST node carries a `NodeAnnotation` (the `EpAnn ann` wrapper) containing:
+
+- **`anchor`** — an `EpaLocation` marking the top-left corner of the node's bounding rectangle.
+ This is the coordinate origin for the node's internal layout.
+- **`anns`** — node-kind-specific annotation payload (keyword token positions, bracket tokens,
+ pragma text, etc.).
+- **`comments`** — all `EpaComment` values logically owned by this node.
+
+No separate annotation map exists. The annotation is embedded directly in the `GenLocated`
+wrapper via the `Anno` type family (the "Trees That Grow" mechanism). The annotation type for
+each node kind is determined statically by its Haskell type.
+
+### 2. Trailing Annotations Are Separate from the Bounding Box
+
+Punctuation that separates list elements — trailing commas, semicolons, vertical bars, and
+constraint arrows — is stored in a `TrailingAnn` list that is _outside_ the node's bounding box.
+
+```
+TrailingAnn
+ ├─ semi — ';'
+ ├─ comma — ','
+ ├─ vbar — '|'
+ └─ darrow — '=>' or '⇒'
+```
+
+The `HasTrailing` typeclass exposes a uniform `trailing` / `setTrailing` interface over all
+annotation types. The printer uses this interface to extract trailing glue without inspecting
+the concrete annotation type.
+
+**Consequence for tooling:** when moving, copying, or deleting a node, a tool operates on the
+anchor span and can transfer or discard trailing annotations independently. There is no risk
+of accidentally duplicating or losing a separator when restructuring a list.
+
+### 3. The Bounding Box Invariant
+
+The `anchor` span is the bounding box of everything the node _owns_:
+
+- **Leading comments** are printed _before_ the anchor and lie _outside_ the bounding box.
+ They may appear at any indentation.
+- **Trailing annotations** are printed _after_ the anchor's end and also lie outside it.
+- The anchor's start position is the top-left corner of the box; the parser widens the span
+ (via `widenAnchorT` / `widenAnchorS`) to cover every token that syntactically belongs to
+ the node.
+
+```
+ leading comment ← outside bounding box; before anchor
+ [anchor start]
+ token token token ← inside bounding box
+ token token
+ [anchor end]
+ , ← trailing annotation; outside bounding box
+```
+
+### 4. Splice Invariance
+
+Moving an entire subtree to a different column requires updating _only the root node's entry
+delta_. No descendant delta needs to change.
+
+This works because `DifferentLine` deltas store the column as `absolute_col − layout_lhs`, where
+`layout_lhs` is the left margin of the enclosing layout block. When the root anchor moves, the
+printer adopts the new column as the new `layout_lhs`. Every child that has a `DifferentLine`
+delta recomputes its absolute column as `new_layout_lhs + stored_col`, sliding the entire subtree
+to the right or left by the same amount.
+
+`SameLine` deltas are unaffected by relocation because they record a gap from the immediately
+preceding token, not from the layout margin.
+
+**Known exceptions:** layout-block terminators such as `in`, `where`, and `of` intentionally
+appear to the _left_ of the block they close. Their `DifferentLine.col` is negative. The
+printer's validity check (`isGoodDelta`) accepts this: for `DifferentLine` it only requires
+`lines > 0`, not that `col ≥ 0`.
+
+### 5. The Zero-Column Invariant for List Items
+
+Nodes that appear as direct children of a layout list (a `where` clause, a `do` block, an
+export list, etc.) always store `DifferentLine(n, 0)` — a zero column offset from the list's
+layout origin.
+
+The list's layout origin is recorded in `AnnList.al_anchor`. The absolute column of each item
+is therefore `al_anchor.col + 0 = al_anchor.col`. This has two consequences:
+
+1. **Reordering is free.** Items can be moved within the list without updating any individual
+ delta; all items already share the same column.
+2. **Relocation is cheap.** Moving the entire list to a new indentation requires updating only
+ `al_anchor`; all items self-correct automatically.
+
+---
+
+## Data Flow
+
+```
+Source file
+ │
+ ▼
+┌─────────────┐
+│ Parser │ getCommentsFor / getPriorCommentsFor / getFinalCommentsFor
+│ (GHC.Parser│ → allocates EpaComments to each AST node (unbalanced form)
+│ + Lexer) │ → all EpaLocations are absolute (EpaSpan)
+└──────┬──────┘
+ │ ParsedSource (absolute annotations)
+ ▼
+┌──────────────────┐
+│ makeDeltaAst │ converts EpaSpan → EpaDelta for every can_update node
+│ (exactPrint.hs) │ adjustDeltaForOffset stores col as (absolute - layout_lhs)
+└──────┬───────────┘
+ │ ParsedSource (relative annotations)
+ ▼
+┌──────────────────────┐
+│ Transform monad │ structural edits: insert/remove/reorder declarations
+│ (Transform.hs) │ setEntryDP, transferEntryDP, balanceCommentsList, …
+└──────┬───────────────┘
+ │ modified ParsedSource
+ ▼
+┌──────────────────┐
+│ exactPrint │ single-pass traversal; undelta(prior_end, dp, layout_lhs)
+│ (ExactPrint.hs) │ comment interleaving; layout block tracking
+└──────┬───────────┘
+ │
+ ▼
+ Source text (byte-for-byte faithful to the original, modulo edits)
+```
+
+---
+
+## The Parser Phase
+
+### Comment Allocation
+
+The GHC parser maintains a comment queue (`comment_q`) of `EpaComment` values seen in the token
+stream but not yet attached to any node. As each grammar production is reduced, the parser drains
+matching comments from the queue:
+
+- `getCommentsFor span node` — moves all comments whose span falls _inside_ `span` into the
+ node's `EpAnn.comments.prior` list.
+- `getPriorCommentsFor span node` — additionally captures comments that fall _just before_ the
+ span (used for top-level declarations to capture preceding Haddock comments).
+- `getFinalCommentsFor module_node` — at EOF, drains the entire queue into the module node.
+
+**Guarantee:** each comment is allocated to exactly one node; the queue is drained monotonically.
+All `EpaComments` produced by the parser are in the `unbalanced` state (only `prior`, no
+`following`).
+
+### `Anno` Type Family
+
+The annotation type for each AST node kind is chosen by the `Anno` type family. Common
+specialisations:
+
+| Type alias | Annotation payload | Used for |
+|---|---|---|
+| `SrcSpanAnnA` | `AnnListItem` | Most expressions, patterns, declarations |
+| `SrcSpanAnnN` | `NameAnn` | Name occurrences |
+| `SrcSpanAnnL` | `AnnList ()` | Plain layout lists |
+| `SrcSpanAnnLW` | `AnnList EpToken` | `where`-clause lists |
+| `SrcSpanAnnP` | `AnnPragma` | `{-# … #-}` pragmas |
+| `SrcSpanAnnC` | `AnnContext` | Constraint contexts `C a =>` |
+
+---
+
+## The Printing Phase
+
+### The `ExactPrint` Typeclass
+
+Every AST constructor that can appear in a located position has an `ExactPrint` instance:
+
+```haskell
+class (Typeable a) => ExactPrint a where
+ getAnnotationEntry :: a -> Entry -- extract anchor + trailing + comments
+ setAnnotationAnchor :: a -> EpaLocation
+ -> [TrailingAnn] -> EpAnnComments -> a -- write anchor back
+ exact :: (Monad m, Monoid w) => a -> EP w m a -- print this constructor
+```
+
+`markAnnotated a = enterAnn (getAnnotationEntry a) a` is the single recursive call site.
+`enterAnn` handles all the cross-cutting concerns (comments, layout, anchor write-back) and
+then delegates to `exact` for the constructor-specific tokens and child traversals. There are
+several hundred `ExactPrint` instances, one for each GHC AST constructor.
+
+The same instance serves both `exactPrint` and `makeDeltaAst`: the output options (`EPOptions`)
+determine whether tokens are accumulated into a string or discarded.
+
+### `makeDeltaAst`
+
+Converts every `EpaSpan` anchor to `EpaDelta` form in a single pass over the AST. The delta
+is computed as:
+
+```
+raw_delta = ss2delta(prior_end_pos, anchor_start)
+stored_delta = adjustDeltaForOffset(layout_lhs, raw_delta)
+ = DifferentLine(lines, absolute_col - layout_lhs)
+```
+
+The inverse during printing (`undelta`) recovers the absolute column:
+
+```
+absolute_col = layout_lhs + stored_delta.col -- DifferentLine
+absolute_col = prior_col + stored_delta.col -- SameLine
+```
+
+This shared traversal runs with no-op output options; no source text is accumulated.
+
+### `exactPrint`
+
+Runs the same traversal as `makeDeltaAst` but with string-accumulating options. For each node:
+
+1. Leading comments (in `EpaDelta.leading_comments`) are printed before the anchor.
+2. The anchor position is resolved (absolute from `EpaSpan`, or via `undelta` for `EpaDelta`).
+3. If `mark_layout` is set, the anchor column becomes the new `layout_lhs` for the block.
+4. Children are visited recursively with the updated layout state.
+
+### Comment Interleaving
+
+Two strategies are used depending on the anchor form:
+
+- **Absolute anchor (`EpaSpan`):** the printer maintains a pool of pending comments sorted by
+ source position. Before each token it emits all pooled comments whose position precedes the
+ token (`printCommentsBefore`, via `commentAllocationBefore`).
+- **Relative anchor (`EpaDelta`):** comments are pre-attached to the node's annotation by
+ `makeDeltaAst` or `balanceCommentsList`. The entire pool is flushed unconditionally via
+ `flushComments`, then the node's own attached comments are printed in order via `printOneComment`.
+
+CPP-injected comments may carry fake filenames ("CPP", "LINE", "SHEBANG") in their spans.
+Ordering always uses `ss2pos` (line, column only) rather than the full `RealSrcSpan` comparator,
+which would sort by filename first and produce incorrect relative ordering.
+
+### Parentheses in Infix Declaration Heads via the Comment Machinery
+
+Infix type-level declarations — type synonyms, data types, class declarations, type families, and
+GADT constructors — may carry optional parentheses around the operator/constructor in the
+declaration head. For example:
+
+```haskell
+type (a `MyOp` b) = ...
+class (a `MyClass` b) where ...
+data (a `MyData` b) = ...
+```
+
+These parentheses are stored as _lists_ of `EpToken` values (`ops`, `cps`) on the declaration's
+annotation (`AnnSynDecl`, `AnnClassDecl`, `AnnFamilyDecl`, `AnnDataDefn`, `AnnConDeclGADT`, and
+`AnnFunRhs` for infix function patterns). They cannot be emitted at a fixed point in the
+structural traversal because the infix head visits the type constructor and its arguments in an
+order that does not naturally interleave with the surrounding parens.
+
+The solution is `epTokensToComments "(" ops` / `epTokensToComments ")" cps`: each present
+`EpToken` is converted to a synthetic `Comment` (with `keyword_origin = "("` or `")"`) and
+injected into the comment pool. The pool is ordered by source position, so these synthetic
+parens are automatically emitted at exactly the right location relative to the other tokens,
+without requiring any explicit position tracking in the `exact` instance.
+
+During `makeDeltaAst`, each synthetic paren's computed delta is captured via `applyComment` and
+embedded in the adjacent token's `EpaDelta` constructor, so the round-trip preserves paren
+positions in delta form too.
+
+### Mixed Bind/Sig Lists
+
+The GHC AST stores function bindings and type signatures in separate sub-lists. The printer
+merges them using a sort key on the `ValBinds` extension point:
+
+- **`NoAnnSortKey` (span order):** sorts by original source span — correct immediately after
+ parsing while spans are still trustworthy.
+- **`AnnSortKey [BindTag]` (tag order):** a sequence of `bind_tag` / `sig_tag` tokens recording
+ the exact interleaving. Set whenever `replaceDeclarations` is called; the printer follows the
+ sequence exactly, enabling caller-controlled reordering.
+
+Class and instance bodies use the same mechanism with four sub-lists and `DeclTag`.
+
+---
+
+## The Transform Phase
+
+The `Transform` monad wraps a state carrying a unique-span counter and a debug log. It exposes
+operations for structural edits while keeping annotations consistent.
+
+The unique-span counter exists to support `uniqueSrcSpanT`, which allocated synthetic `SrcSpan`
+values (line = -1) for freshly created AST nodes. That function is now dead code: it is exported
+for API compatibility but is called nowhere in GHC or `check-exact`. New nodes are given
+`EpaDelta` locations directly, which need no unique span. The counter field in `TransformState`
+is therefore vestigial and should be removed together with `uniqueSrcSpanT` and `isUniqueSrcSpan`
+in a future cleanup.
+
+### Declaration Access
+
+- **`getDeclarations node`** — returns the declaration list of a module, match, let-binding,
+ pattern-binding where clause, or class/instance body as a `DeclarationList`.
+- **`replaceDeclarations node new_decls`** — replaces the list; implicitly records the new
+ ordering as a tag-order `AnnSortKey`, so the printer will honour the caller's order regardless
+ of original source spans. **Passing an empty list collapses the underlying `HsLocalBinds` to
+ `EmptyLocalBinds`, which drops the `where` keyword annotation entirely** — this is not a no-op
+ on the container structure.
+
+A key responsibility of `getDeclarations` is **normalising `ValBinds`**. Inside a
+`HsLocalBinds` / `ValBinds` node (a `where` clause, `let` expression, `let` statement, or
+pattern-binding where clause), GHC stores function bindings and type signatures in two _separate_
+sub-collections: a `Bag` of `LHsBind` and a `[LSig]`. These are physically disjoint from each
+other and have no guaranteed ordering relative to each other.
+
+`getDeclarations` (via `hsDeclsLocalBinds` → `hsDeclsValBinds` → `orderedDeclsBinds`) merges
+them back into a single `[LHsDecl]` in source order:
+
+- **`NoAnnSortKey` (freshly parsed):** sorts the combined list by `RealSrcSpan`, recovering the
+ original interleaved order from the absolute source positions.
+- **`AnnSortKey [BindTag]` (after any structural edit):** replays the tag sequence recorded by
+ `captureOrderBinds`, drawing from the binds bag or sigs list according to each tag.
+
+The result is a physically ordered, uniform list of `LHsDecl` values — binds wrapped in `ValD`,
+sigs wrapped in `SigD` — that the exact-print and transformation machinery can traverse and edit
+without knowing or caring that the underlying storage splits them across two separate containers.
+`replaceDeclarations` is the inverse: it re-separates the uniform list back into the two
+sub-collections via `decl2Bind` / `decl2Sig` and records a fresh `AnnSortKey` for the new order.
+
+### Positioning Nodes
+
+- **`setEntryDP node dp`** — sets the entry delta of a node, converting its anchor to relative
+ form. Must be called before inserting a freshly constructed node.
+- **`getEntryDP node`** — reads the current entry delta (default `SameLine 0` if absent).
+- **`transferEntryDP source target`** — moves the entry delta _and_ leading comments from one
+ node to another. Used when a removed declaration's successor needs to inherit its spacing.
+
+### Inserting and Removing Declarations
+
+**`insertDeclaration node decl point`** inserts `decl` at `point` (start, end, before/after a
+named item). The inserted node must already have a relative anchor. All existing declarations
+are comment-balanced before the structural change.
+
+**`removeDeclaration node decl`** removes `decl`. The caller must then call `transferEntryDP`
+or `setEntryDP` on the new first declaration to absorb the gap.
+
+### Comment Balancing
+
+After parsing, all comments are in the `prior` list of the nodes that saw them first. The
+`balanceComments` / `balanceCommentsList` operations redistribute them:
+
+- A comment ≤ 1 blank line below declaration D stays with D as a `following` comment.
+- A comment > 1 blank line below D migrates to the `prior` list of D's successor.
+
+The operation is **idempotent**: running it twice produces the same result because `balanced` is
+a terminal state (`unbalanced → balanced`; no transition out of `balanced` is defined).
+
+For `FunBind` nodes the balancing is hierarchical: comments are first balanced at the binding
+level, then distributed among the individual match equations within the binding.
+
+### Capturing Spacing Before Edits
+
+Before removing or reordering declarations, spacing must be encoded in relative form so it
+survives the structural change. If `makeDeltaAst` has **not** been called, the AST still
+carries absolute `EpaSpan` anchors; the spacing functions below derive relative deltas from those
+absolute positions and write them back, making subsequent structural edits safe. If `makeDeltaAst`
+**has** already been called, the anchors are already in `EpaDelta` form and these functions are
+idempotent — they recompute the same delta values that `makeDeltaAst` already stored.
+
+- **`captureLineSpacing decls`** — sets each declaration's entry delta lines to the actual blank
+ lines between it and its predecessor.
+- **`captureMatchLineSpacing decl`** — same, within the match equations of a `FunBind`.
+- **`captureTypeSigSpacing sig`** — captures spacing within a multi-name type signature.
+- **`addModuleCommentOrigDeltas module`** — converts module-level comment spans from absolute to
+ relative form before the module's declaration list is replaced.
+
+---
+
+## CPP Support
+
+Source files using `{-# LANGUAGE CPP #-}` present a special challenge: the GHC parser sees
+the _preprocessed_ text, which may differ substantially from the original source (directives
+removed, macros expanded).
+
+### Pipeline
+
+```
+Original source
+ │
+ ├─ getPreprocessorAsComments ─→ directive line tokens (real filename)
+ │
+ ├─ stripLinePragmas / tokeniseOriginalSrc ─→ directive-stripped token stream
+ │
+ └─ getPreprocessedSrcDirect ─→ C-preprocessed text
+ └─ lexTokenStream ─→ post-CPP token stream
+ │
+ └─ getCppTokens ─→ three-way merge
+ ─→ MergedCppComments
+```
+
+`getCppTokens` identifies directive tokens present in the original source but absent from the
+preprocessed output (consumed by CPP) and converts them to synthetic `ITlineComment` tokens.
+These are merged with the directive lines extracted directly to form `injected_comments`.
+
+**Limitation:** the three-way merge is correct only in `-nomacro` mode. Macro expansion
+introduces expanded tokens that are not recoverable by span-based matching.
+
+### Insertion
+
+`insertCppComments module injected_comments` splices the synthetic comments back into the parsed
+AST using a bottom-up traversal (`everywhereM`): each `EpAnn` node claims the injected comments
+whose source span it encloses. Remaining comments are distributed to module-level positions by
+`insertTopLevelCppComments`. CPP-aware ordering (`ss2pos`, ignoring filenames) is used
+throughout.
+
+After `insertCppComments`, the round-trip guarantee extends to CPP-enabled sources:
+`exactPrint(insertCppComments(parseModuleEpAnnsWithCpp(f)))` reproduces `f` byte-for-byte.
+
+---
+
+## Correctness Guarantees
+
+| Guarantee | Statement |
+|---|---|
+| **RoundTripFidelity** | For any file `f` parsed by GHC, `exactPrint(makeDeltaAst(parse(f)))` is byte-identical to `f` (modulo tab expansion). |
+| **AllCommentsEmitted** | After a complete `exactPrint` traversal, every comment attached to the AST has been emitted exactly once and the pending pool is empty. |
+| **CursorNonDecreasing** | The output cursor only moves forward; tokens are emitted in source order. |
+| **CommentsAllocatedAtMostOnce** | Each comment in the parser's queue is moved to exactly one AST node; once removed it is never re-added. |
+| **BalanceIsIdempotent** | `balanceCommentsList` can be called multiple times on the same list without duplicating or losing comments. |
+| **ReplacePreservesCallerOrder** | After `replaceDeclarations(node, new_decls)`, the printer outputs declarations in the same order as `new_decls`. |
+| **RoundTripWithCpp** | For CPP-enabled files, `exactPrint(insertCppComments(parseModuleEpAnnsWithCpp(f)))` reproduces `f` byte-for-byte (no-macro mode only). |
+
+---
+
+## Typical Tool Workflow
+
+A refactoring tool that wants to add a new top-level declaration does the following:
+
+```
+1. parseModuleEpAnnsWithCpp opts libdir file -- parse with CPP support
+2. insertCppComments parsed_source comments -- re-insert CPP/LINE/SHEBANG comments
+3. makeDeltaAst parsed_source -- convert absolute spans to deltas
+4. runTransform do
+ addModuleCommentOrigDeltas module -- protect module-level comments
+ decls ← getDeclarations module -- read current declaration list
+ captureLineSpacing decls -- encode spacing before edits
+ balanceCommentsList decls -- redistribute comments
+ setEntryDP new_decl (DifferentLine 2 0) -- position the new declaration
+ replaceDeclarations module (decls ++ [new_decl])
+5. exactPrint modified_source -- emit the result
+```
+
+The result is the original source with the new declaration appended, all original comments and
+layout preserved, and a diff that contains only the added lines.
=====================================
compiler/GHC/Hs/Expr.hs
=====================================
@@ -2620,7 +2620,7 @@ FieldLabelStrings
instance (UnXRec p, Outputable (XRec p FieldLabelString)) => Outputable (FieldLabelStrings p) where
ppr (FieldLabelStrings flds) =
- hcat (punctuate dot (toList $ NE.map (ppr . unXRec @p) flds))
+ hcat (punctuate dot (toList $ NE.map ppr flds))
instance (UnXRec p, Outputable (XRec p FieldLabelString)) => OutputableBndr (FieldLabelStrings p) where
pprInfixOcc = pprFieldLabelStrings
@@ -2632,7 +2632,7 @@ instance (UnXRec p, Outputable (XRec p FieldLabelString)) => OutputableBndr (Lo
pprFieldLabelStrings :: forall p. (UnXRec p, Outputable (XRec p FieldLabelString)) => FieldLabelStrings p -> SDoc
pprFieldLabelStrings (FieldLabelStrings flds) =
- hcat (punctuate dot (toList $ NE.map (ppr . unXRec @p) flds))
+ hcat (punctuate dot (toList $ NE.map ppr flds))
pprPrefixFastString :: FastString -> SDoc
pprPrefixFastString fs = pprPrefixOcc (mkVarUnqual fs)
@@ -2677,8 +2677,6 @@ type instance Anno FastString = EpAnnCO
type instance Anno HText = EpAnnCO
-- Used in HsQuasiQuote and perhaps elsewhere
-type instance Anno (DotFieldOcc (GhcPass p)) = EpAnnCO
-
instance (HasAnnotation (Anno a))
=> WrapXRec (GhcPass p) a where
wrapXRec = noLocA
=====================================
compiler/GHC/Parser.y
=====================================
@@ -3283,12 +3283,12 @@ aexp2 :: { ECP }
amsA' (sLL $1 $> $ HsCmdArrForm (AnnList (glRM $1) (ListBanana (epUniTok $1) (epUniTok $4)) [] []) $2 Prefix
(reverse $3)) }
-projection :: { Located (NonEmpty (LocatedAn NoEpAnns (DotFieldOcc GhcPs))) }
+projection :: { Located (NonEmpty (DotFieldOcc GhcPs)) }
projection
-- See Note [Whitespace-sensitive operator parsing] in GHC.Parsing.Lexer
: projection TIGHT_INFIX_PROJ field
- { sLL $1 $> ((sLLa $2 $> $ DotFieldOcc (AnnFieldLabel (Just $ epTok $2)) $3) `NE.cons` unLoc $1) }
- | PREFIX_PROJ field { sLL $1 $> ((sLLa $1 $> $ DotFieldOcc (AnnFieldLabel (Just $ epTok $1)) $2) :| [])}
+ { sLL $1 $> ((DotFieldOcc (AnnFieldLabel (Just $ epTok $2)) $3) `NE.cons` unLoc $1) }
+ | PREFIX_PROJ field { sLL $1 $> ((DotFieldOcc (AnnFieldLabel (Just $ epTok $1)) $2) :| [])}
splice_exp :: { LHsExpr GhcPs }
: splice_untyped { fmap (HsUntypedSplice noExtField) (reLoc $1) }
@@ -3772,11 +3772,11 @@ fbind :: { forall b. DisambECP b => PV (Fbind b) }
fmap Right $ mkHsProjUpdatePV l (L l fields) var isPun Nothing
}
-fieldToUpdate :: { Located [LocatedAn NoEpAnns (DotFieldOcc GhcPs)] }
+fieldToUpdate :: { Located [DotFieldOcc GhcPs] }
fieldToUpdate
-- See Note [Whitespace-sensitive operator parsing] in Lexer.x
- : fieldToUpdate TIGHT_INFIX_PROJ field { sLL $1 $> ((sLLa $2 $> (DotFieldOcc (AnnFieldLabel $ Just $ epTok $2) $3)) : unLoc $1) }
- | field { sL1 $1 [sL1a $1 (DotFieldOcc (AnnFieldLabel Nothing) $1)] }
+ : fieldToUpdate TIGHT_INFIX_PROJ field { sLL $1 $> ((DotFieldOcc (AnnFieldLabel $ Just $ epTok $2) $3) : unLoc $1) }
+ | field { sL1 $1 [DotFieldOcc (AnnFieldLabel Nothing) $1] }
-----------------------------------------------------------------------------
-- Implicit Parameter Bindings
=====================================
compiler/GHC/Parser/PostProcess.hs
=====================================
@@ -3768,7 +3768,7 @@ starSym NormalSyntax = fsLit "*"
-----------------------------------------
-- Bits and pieces for RecordDotSyntax.
-mkRdrGetField :: LHsExpr GhcPs -> LocatedAn NoEpAnns (DotFieldOcc GhcPs)
+mkRdrGetField :: LHsExpr GhcPs -> DotFieldOcc GhcPs
-> HsExpr GhcPs
mkRdrGetField arg field =
HsGetField {
@@ -3777,11 +3777,11 @@ mkRdrGetField arg field =
, gf_field = field
}
-mkRdrProjection :: NonEmpty (LocatedAn NoEpAnns (DotFieldOcc GhcPs)) -> AnnProjection -> HsExpr GhcPs
+mkRdrProjection :: NonEmpty (DotFieldOcc GhcPs) -> AnnProjection -> HsExpr GhcPs
mkRdrProjection flds anns =
HsProjection {
proj_ext = anns
- , proj_flds = fmap unLoc flds
+ , proj_flds = flds
}
mkRdrProjUpdate :: SrcSpanAnnA -> Located (NonEmpty (LocatedAn NoEpAnns (DotFieldOcc GhcPs)))
=====================================
compiler/GHC/Tc/Types/Origin.hs
=====================================
@@ -627,9 +627,9 @@ exprCtOrigin (HsQual {}) = Shouldn'tHappenOrigin "constraint context" -
exprCtOrigin (HsFunArr {}) = Shouldn'tHappenOrigin "function arrow" -- See Note [Types in terms]
exprCtOrigin (ExplicitList {}) = ListOrigin
exprCtOrigin (HsIf {}) = IfThenElseOrigin
-exprCtOrigin (HsProjection _ p) = RecordFieldProjectionOrigin (FieldLabelStrings $ fmap noLocA p)
+exprCtOrigin (HsProjection _ p) = RecordFieldProjectionOrigin (FieldLabelStrings p)
exprCtOrigin (RecordUpd{}) = RecordUpdOrigin
-exprCtOrigin (HsGetField _ _ f) = GetFieldOrigin (fmap (mkFastStringShortText . field_label) $ dfoLabel (unLoc f))
+exprCtOrigin (HsGetField _ _ f) = GetFieldOrigin (fmap (mkFastStringShortText . field_label) $ dfoLabel f)
exprCtOrigin (XExpr (ExpandedThingRn (HSE o _))) = hsCtxtCtOrigin o
exprCtOrigin (XExpr (HsRecSelRn f)) = OccurrenceOfRecSel $ L (getLoc $ foLabel f) (foExt f)
=====================================
compiler/Language/Haskell/Syntax/Expr.hs
=====================================
@@ -117,7 +117,7 @@ values (see function @mkRdrRecordUpd@ in 'GHC.Parser.PostProcess').
type LFieldLabelStrings p = XRec p (FieldLabelStrings p)
newtype FieldLabelStrings p =
- FieldLabelStrings (NonEmpty (XRec p (DotFieldOcc p)))
+ FieldLabelStrings (NonEmpty (DotFieldOcc p))
-- Field projection updates (e.g. @foo.bar.baz = 1@). See Note
-- [RecordDotSyntax field updates].
@@ -452,7 +452,7 @@ data HsExpr p
| HsGetField {
gf_ext :: XGetField p
, gf_expr :: LHsExpr p
- , gf_field :: XRec p (DotFieldOcc p)
+ , gf_field :: DotFieldOcc p
}
-- | Record field selector. e.g. @(.x)@ or @(.x.y)@
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b387aa7adc89a4c18a8190d45d43e1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b387aa7adc89a4c18a8190d45d43e1…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/az/exactprint-annotation-rationalisation] 23 commits: Improve error messages for invalid record wildcards
by Alan Zimmerman (@alanz) 21 Jul '26
by Alan Zimmerman (@alanz) 21 Jul '26
21 Jul '26
Alan Zimmerman pushed to branch wip/az/exactprint-annotation-rationalisation at Glasgow Haskell Compiler / GHC
Commits:
c2f6dcd4 by Sasha Bogicevic at 2026-07-20T10:31:56+02:00
Improve error messages for invalid record wildcards
Record wildcard hints are now shown in more contexts and include
constructor arity; matching with `..` on a fieldless constructor
now produces a dedicated error message.
Fixes #21101
- - - - -
4c02e76b by Duncan Coutts at 2026-07-21T10:37:21-04:00
Mark test T27105 as fragile, citing issue #27522
Scheduler fairness is fine, except when it isn't. And it isn't on CI
machines surprisingly often! See the issue for details.
- - - - -
d29ecece by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Keep decls together in ClassDecl
Similar to 1718230f4d3d19d8c49c0e5d496cb0fb6f399528 for HsValBindsLR,
this commit updates ClassDecl so that it no longer splits out the
assorted `LHsDecl GhcPs` until the renamer.
It does this by inserting a type family (separate from the classic TTG one) for this.
So
data TyClDecl
...
| ClassDecl {
...
tcdDecls :: XClassDecls pass
with
type instance XClassDecls GhcPs = [LHsDecl GhcPs]
type instance XClassDecls GhcRn = ClassDeclX GhcRn
type instance XClassDecls GhcTc = ClassDeclX GhcTc
data ClassDeclX pass
= ClassDeclX { tcdSigs :: [LSig pass], -- ^ Methods' signatures
tcdMeths :: LHsBinds pass, -- ^ Default methods
tcdATs :: [LFamilyDecl pass], -- ^ Associated types;
tcdATDefs :: [LTyFamDefltDecl pass], -- ^ Associated type defaults
tcdDocs :: [LDocDecl pass] -- ^ Haddock docs
}
- - - - -
43a54fd3 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: ClsInstDecl as list in GhcPs
- - - - -
fbfc2751 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedP from OverlapMode
- - - - -
feb416ac by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedP from CType
- - - - -
e6581225 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedP, last use in WarningTxt
- - - - -
87426abf by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedE from WarningCategory
- - - - -
6d9d97b2 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocateE from XCImport and XCExport
- - - - -
d1e07582 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedE from HsRecFields dot
- - - - -
07f2acce by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedE completely, last usage for pats
- - - - -
76a461a7 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove AnnList (EpToken "where") usages
This is moving toward removing the parameter from AnnList completely
- - - - -
3c4c9362 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA remove AnnList (EpToken "rec") usages
- - - - -
79e2f451 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove last parameterised AnnList usage (EpaLocation)
Also remove the parameter
- - - - -
1807bcc6 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
TTG: Add extension points to BooleanFormula
They are currently unused, but will be used for exact print annotations next
- - - - -
577ba7c2 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Remove LocatedBC / SrcSpanBF
- - - - -
336a113f by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: remove unused addTrailingAnnToL. Squash appropriately
- - - - -
78957abb by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPS: Remove NoEpTok/NoEpUniTok, using an unhelpful SrcSpan instead
Also introduce helper functions noEpTok and noEpUniTok to serve
as simple replacements in code inserting an token annotation without
location information.
- - - - -
53d0b7ce by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Some haddock processing tweaks
- - - - -
33660fae by Alan Zimmerman at 2026-07-21T18:30:13+01:00
Some haddock exactprint tests
- - - - -
0808acd9 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: When adding comments honour trailing anns
- - - - -
c66d7de8 by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Uses Parsers.parseModule for exactprint tests
This is the advertised way to parse for use for exact printing in the
ghc-exactprint library, make sure we test using it.
- - - - -
b387aa7a by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA Fix HsCmdDo exact print with comments
TODO: add test based on proc-do-complex-four-out.hs
- - - - -
99 changed files:
- + changelog.d/21101
- compiler/GHC/Builtin/Utils.hs
- compiler/GHC/Core/Class.hs
- compiler/GHC/CoreToIface.hs
- compiler/GHC/Data/BooleanFormula.hs
- compiler/GHC/Hs.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Decls/Overlap.hs
- compiler/GHC/Hs/Dump.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Pat.hs
- compiler/GHC/Hs/Stats.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Syntax.hs
- compiler/GHC/Iface/Warnings.hs
- compiler/GHC/IfaceToCore.hs
- compiler/GHC/Parser.y
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Class.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/Utils/Env.hs
- compiler/GHC/Tc/Utils/Instantiate.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Types/GREInfo.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/GHC/Unit/Module/Warnings.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/BooleanFormula.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- testsuite/tests/concurrent/should_run/T27105.hs
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/ghc-api/T25121_status.stdout
- testsuite/tests/ghc-api/exactprint/T22919.stderr
- testsuite/tests/ghc-api/exactprint/Test20239.stderr
- testsuite/tests/ghc-api/exactprint/ZeroWidthSemi.stderr
- testsuite/tests/haddock/haddock_examples/haddock.Test.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T24221.stderr
- testsuite/tests/module/mod185.stderr
- testsuite/tests/parser/should_compile/DumpParsedAst.stderr
- testsuite/tests/parser/should_compile/DumpParsedAstComments.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/DumpTypecheckedAst.stderr
- testsuite/tests/parser/should_compile/KindSigs.stderr
- testsuite/tests/parser/should_compile/T14189.stderr
- testsuite/tests/parser/should_compile/T15279.stderr
- testsuite/tests/parser/should_compile/T15323.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/parser/should_compile/T20718.stderr
- testsuite/tests/parser/should_compile/T20718b.stderr
- testsuite/tests/parser/should_compile/T20846.stderr
- testsuite/tests/parser/should_compile/T23315/T23315.stderr
- testsuite/tests/printer/AnnotationNoListTuplePuns.stdout
- + testsuite/tests/printer/Haddock1.hs
- testsuite/tests/printer/Makefile
- testsuite/tests/printer/T18791.stderr
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/printer/Test24533.stdout
- testsuite/tests/printer/all.T
- + testsuite/tests/rename/should_fail/T21101.hs
- + testsuite/tests/rename/should_fail/T21101.stderr
- testsuite/tests/rename/should_fail/T9815.stderr
- testsuite/tests/rename/should_fail/T9815b.stderr
- testsuite/tests/rename/should_fail/T9815bghci.stderr
- testsuite/tests/rename/should_fail/T9815ghci.stderr
- testsuite/tests/rename/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Parsers.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cf57b346bb530d37ca67b9bc942f3a…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/cf57b346bb530d37ca67b9bc942f3a…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/az/epa-tidy-locatedxxx-8] 3 commits: Improve error messages for invalid record wildcards
by Alan Zimmerman (@alanz) 21 Jul '26
by Alan Zimmerman (@alanz) 21 Jul '26
21 Jul '26
Alan Zimmerman pushed to branch wip/az/epa-tidy-locatedxxx-8 at Glasgow Haskell Compiler / GHC
Commits:
c2f6dcd4 by Sasha Bogicevic at 2026-07-20T10:31:56+02:00
Improve error messages for invalid record wildcards
Record wildcard hints are now shown in more contexts and include
constructor arity; matching with `..` on a fieldless constructor
now produces a dedicated error message.
Fixes #21101
- - - - -
4c02e76b by Duncan Coutts at 2026-07-21T10:37:21-04:00
Mark test T27105 as fragile, citing issue #27522
Scheduler fairness is fine, except when it isn't. And it isn't on CI
machines surprisingly often! See the issue for details.
- - - - -
d29ecece by Alan Zimmerman at 2026-07-21T18:30:13+01:00
EPA: Keep decls together in ClassDecl
Similar to 1718230f4d3d19d8c49c0e5d496cb0fb6f399528 for HsValBindsLR,
this commit updates ClassDecl so that it no longer splits out the
assorted `LHsDecl GhcPs` until the renamer.
It does this by inserting a type family (separate from the classic TTG one) for this.
So
data TyClDecl
...
| ClassDecl {
...
tcdDecls :: XClassDecls pass
with
type instance XClassDecls GhcPs = [LHsDecl GhcPs]
type instance XClassDecls GhcRn = ClassDeclX GhcRn
type instance XClassDecls GhcTc = ClassDeclX GhcTc
data ClassDeclX pass
= ClassDeclX { tcdSigs :: [LSig pass], -- ^ Methods' signatures
tcdMeths :: LHsBinds pass, -- ^ Default methods
tcdATs :: [LFamilyDecl pass], -- ^ Associated types;
tcdATDefs :: [LTyFamDefltDecl pass], -- ^ Associated type defaults
tcdDocs :: [LDocDecl pass] -- ^ Haddock docs
}
- - - - -
51 changed files:
- + changelog.d/21101
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Stats.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Parser/PostProcess/Haddock.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/TyCl/Class.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/GREInfo.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Decls.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- testsuite/tests/concurrent/should_run/T27105.hs
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/haddock/haddock_examples/haddock.Test.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544.stderr
- testsuite/tests/haddock/should_compile_flag_haddock/T17544_kw.stderr
- testsuite/tests/parser/should_compile/DumpRenamedAst.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- testsuite/tests/parser/should_compile/T20452.stderr
- testsuite/tests/printer/Test24533.stdout
- + testsuite/tests/rename/should_fail/T21101.hs
- + testsuite/tests/rename/should_fail/T21101.stderr
- testsuite/tests/rename/should_fail/T9815.stderr
- testsuite/tests/rename/should_fail/T9815b.stderr
- testsuite/tests/rename/should_fail/T9815bghci.stderr
- testsuite/tests/rename/should_fail/T9815ghci.stderr
- testsuite/tests/rename/should_fail/all.T
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Utils.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Hoogle.hs
- utils/haddock/haddock-api/src/Haddock/Backends/LaTeX.hs
- utils/haddock/haddock-api/src/Haddock/Backends/Xhtml/Decl.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- utils/haddock/haddock-api/src/Haddock/GhcUtils.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Create.hs
- utils/haddock/haddock-api/src/Haddock/Interface/Rename.hs
- utils/haddock/haddock-api/src/Haddock/Types.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b6ce9a30ce4d227002fd283bdc765f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b6ce9a30ce4d227002fd283bdc765f…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/jeltsch/textual-bytecode-output] 2 commits: Remove superfluous `where`
by Wolfgang Jeltsch (@jeltsch) 21 Jul '26
by Wolfgang Jeltsch (@jeltsch) 21 Jul '26
21 Jul '26
Wolfgang Jeltsch pushed to branch wip/jeltsch/textual-bytecode-output at Glasgow Haskell Compiler / GHC
Commits:
aaaf9600 by Wolfgang Jeltsch at 2026-07-21T19:17:36+03:00
Remove superfluous `where`
- - - - -
2a660be0 by Wolfgang Jeltsch at 2026-07-21T19:44:40+03:00
Switch to snake case for local identifiers
- - - - -
1 changed file:
- compiler/GHC/ByteCode/Show.hs
Changes:
=====================================
compiler/GHC/ByteCode/Show.hs
=====================================
@@ -110,36 +110,36 @@ pprOnDiskModuleByteCodeHash = entry (text "hash") . ppr
pprCompiledByteCode :: Module -- ^ The enclosing module
-> CompiledByteCode -- ^ The bytecode
-> SDoc -- ^ The textual information
-pprCompiledByteCode currentModule CompiledByteCode {..}
+pprCompiledByteCode current_module CompiledByteCode {..}
= vcat [
- pprByteCodeObjects currentModule $ bc_bcos,
- pprDataConstructorInfoTables $ bc_itbls,
- pprTopLevelStrings $ bc_strs,
- pprBreakpoints currentModule $ bc_breaks,
- pprStaticPointerTableEntries $ bc_spt_entries,
- pprHPCInfo $ bc_hpc_info
+ pprByteCodeObjects current_module $ bc_bcos,
+ pprDataConstructorInfoTables $ bc_itbls,
+ pprTopLevelStrings $ bc_strs,
+ pprBreakpoints current_module $ bc_breaks,
+ pprStaticPointerTableEntries $ bc_spt_entries,
+ pprHPCInfo $ bc_hpc_info
]
-- | Constructs textual information about bytecode objects.
pprByteCodeObjects :: Module -- ^ The enlosing module
-> FlatBag UnlinkedBCO -- ^ The bytecode objects
-> SDoc -- ^ The textual information
-pprByteCodeObjects currentModule = entry (text "objects") .
- vcatOrNone .
- map (pprByteCodeObject currentModule) .
- elemsFlatBag
+pprByteCodeObjects current_module = entry (text "objects") .
+ vcatOrNone .
+ map (pprByteCodeObject current_module) .
+ elemsFlatBag
-- | Constructs textual information about a single bytecode object.
pprByteCodeObject :: Module -- ^ The enclosing module
-> UnlinkedBCO -- ^ The bytecode object
-> SDoc -- ^ The textual information
-pprByteCodeObject currentModule byteCodeObject = case byteCodeObject of
+pprByteCodeObject current_module byte_code_object = case byte_code_object of
UnlinkedBCO {..}
-> entry (text "ordinary object" <+> quotes (ppr unlinkedBCOName)) $
vcat [
- pprArity $ unlinkedBCOArity,
- pprLiterals currentModule $ unlinkedBCOLits,
- pprPointers currentModule $ unlinkedBCOPtrs
+ pprArity $ unlinkedBCOArity,
+ pprLiterals current_module $ unlinkedBCOLits,
+ pprPointers current_module $ unlinkedBCOPtrs
]
UnlinkedStaticCon {..}
-> entry (
@@ -148,11 +148,15 @@ pprByteCodeObject currentModule byteCodeObject = case byteCodeObject of
)
$
vcat [
- pprDataConstructorName $ unlinkedStaticConDataConName,
- pprLiftedness $ not unlinkedStaticConIsUnlifted,
- pprLiterals currentModule $ unlinkedStaticConLits,
- pprPointers currentModule $ unlinkedStaticConPtrs
+ pprDataConstructorName $ unlinkedStaticConDataConName,
+ pprLiftedness $ isLifted,
+ pprLiterals current_module $ unlinkedStaticConLits,
+ pprPointers current_module $ unlinkedStaticConPtrs
]
+ where
+
+ isLifted :: Bool
+ isLifted = not unlinkedStaticConIsUnlifted
-- | Constructs textual information about the arity of an ordinary bytecode
-- object.
@@ -173,16 +177,16 @@ pprLiftedness = entry (text "lifted") . noOrYes
pprLiterals :: Module -- ^ The enclosing module
-> FlatBag BCONPtr -- ^ The literals
-> SDoc -- ^ The textual information
-pprLiterals currentModule = entry (text "literals") .
- vcatOrNone .
- map (pprLiteral currentModule) .
- elemsFlatBag
+pprLiterals current_module = entry (text "literals") .
+ vcatOrNone .
+ map (pprLiteral current_module) .
+ elemsFlatBag
-- | Constructs textual information about a single literal.
pprLiteral :: Module -- ^ The enclosing module
-> BCONPtr -- ^ The literal
-> SDoc -- ^ The textual information
-pprLiteral currentModule literal = case literal of
+pprLiteral current_module literal = case literal of
BCONPtrWord word
-> text "word" <+>
ppr word
@@ -195,9 +199,9 @@ pprLiteral currentModule literal = case literal of
BCONPtrAddr addrName
-> text "address" <+>
quotes (ppr addrName)
- BCONPtrStr encodedString
+ BCONPtrStr encoded_string
-> text "top-level string" <+>
- text (show (utf8DecodeByteString encodedString))
+ text (show (utf8DecodeByteString encoded_string))
BCONPtrFS string
-> text "top-level string" <+>
text (show (unpackFS string))
@@ -206,7 +210,7 @@ pprLiteral currentModule literal = case literal of
quotes (pprFFIInfo ffiInfo)
BCONPtrCostCentre breakpointID
-> text "cost center of breakpoint" <+>
- pprInternalBreakpointID currentModule breakpointID
+ pprInternalBreakpointID current_module breakpointID
-- | Constructs textual information about FFI info.
pprFFIInfo :: FFIInfo -> SDoc
@@ -216,21 +220,21 @@ pprFFIInfo FFIInfo {..}
-- | Constructs textual information about an FFI type.
pprFFIType :: FFIType -> SDoc
-pprFFIType ffiType = assert (take 3 ident == "FFI") $ text (drop 3 ident) where
+pprFFIType ffi_type = assert (take 3 ident == "FFI") $ text (drop 3 ident) where
ident :: String
- ident = show ffiType
+ ident = show ffi_type
-- | Constructs textual information about the ID of a bytecode breakpoint.
pprInternalBreakpointID
:: Module -- ^ The enclosing module
-> InternalBreakpointId -- ^ The ID of the bytecode breakpoint
-> SDoc -- ^ The textual information
-pprInternalBreakpointID currentModule InternalBreakpointId {..}
- | ibi_info_mod == currentModule = indexDoc
- | otherwise = indexDoc <+>
- text "in" <+>
- ppr ibi_info_mod
+pprInternalBreakpointID current_module InternalBreakpointId {..}
+ | ibi_info_mod == current_module = indexDoc
+ | otherwise = indexDoc <+>
+ text "in" <+>
+ ppr ibi_info_mod
where
indexDoc :: SDoc
@@ -240,22 +244,22 @@ pprInternalBreakpointID currentModule InternalBreakpointId {..}
pprPointers :: Module -- ^ The enclosing module
-> FlatBag BCOPtr -- ^ The pointers
-> SDoc -- ^ The textual information
-pprPointers currentModule = entry (text "utilized items") .
- vcatOrNone .
- map (pprPointer currentModule) .
- elemsFlatBag
+pprPointers current_module = entry (text "utilized items") .
+ vcatOrNone .
+ map (pprPointer current_module) .
+ elemsFlatBag
-- | Constructs textual information about a single pointer.
pprPointer :: Module -- ^ The enclosing module
-> BCOPtr -- ^ The pointer
-> SDoc -- ^ The textual information
-pprPointer currentModule pointer = case pointer of
+pprPointer current_module pointer = case pointer of
BCOPtrName name
-> text "item named" <+> quotes (ppr name)
BCOPtrPrimOp primOp
-> text "primitive operation" <+> quotes (ppr primOp)
- BCOPtrBCO byteCodeObject
- -> pprByteCodeObject currentModule byteCodeObject
+ BCOPtrBCO byte_code_object
+ -> pprByteCodeObject current_module byte_code_object
BCOPtrBreakArray breakArrayModule
-> text "break array of module" <+> quotes (ppr breakArrayModule)
@@ -290,37 +294,37 @@ pprTopLevelStrings = entry (text "top-level strings") .
-- | Constructs textual information about a single top-level string.
pprTopLevelString :: Name -> ByteString -> SDoc
-pprTopLevelString stringName encodedString = entry (ppr stringName) $
- text $
- show $
- utf8DecodeByteString $
- encodedString
+pprTopLevelString string_name encoded_string = entry (ppr string_name) $
+ text $
+ show $
+ utf8DecodeByteString $
+ encoded_string
-- | Constructs textual information about breakpoints.
pprBreakpoints :: Module -- ^ The enclosing module
-> Maybe InternalModBreaks -- ^ The breakpoints
-> SDoc -- ^ The textual information
-pprBreakpoints currentModule
+pprBreakpoints current_module
= entry (text "breakpoints") .
- maybe (text "<none>") (pprActualBreakpoints currentModule)
+ maybe (text "<none>") (pprActualBreakpoints current_module)
-- | Constructs textual information about actual breakpoints.
pprActualBreakpoints :: Module -- ^ The enclosing module
-> InternalModBreaks -- ^ The actual breakpoints
-> SDoc -- ^ The textual information
-pprActualBreakpoints currentModule InternalModBreaks {..}
+pprActualBreakpoints current_module InternalModBreaks {..}
= vcat [
- pprSourceBreakpoints currentModule $ imodBreaks_modBreaks,
- pprByteCodeBreakpoints currentModule $ imodBreaks_breakInfo
+ pprSourceBreakpoints current_module $ imodBreaks_modBreaks,
+ pprByteCodeBreakpoints current_module $ imodBreaks_breakInfo
]
-- | Constructs textual information about source breakpoints.
pprSourceBreakpoints :: Module -- ^ The enclosing module
-> ModBreaks -- ^ The source breakpoints
-> SDoc -- ^ The textual information
-pprSourceBreakpoints currentModule ModBreaks {..}
+pprSourceBreakpoints current_module ModBreaks {..}
= entry (text "source breakpoints") $
- assert (modBreaks_module == currentModule) $
+ assert (modBreaks_module == current_module) $
assert (bounds modBreaks_locs_ == bounds modBreaks_decls) $
assert (bounds modBreaks_locs_ == bounds modBreaks_vars) $
vcatOrNone $
@@ -363,10 +367,10 @@ pprFreeVariables = entry (text "free variables") . vcatOrNone . map ppr
pprByteCodeBreakpoints :: Module -- ^ The enclosing module
-> IntMap CgBreakInfo -- ^ The bytecode breakpoints
-> SDoc -- ^ The textual information
-pprByteCodeBreakpoints currentModule
- = entry (text "bytecode breakpoints") .
- vcatOrNone .
- map (uncurry (pprByteCodeBreakpoint currentModule)) .
+pprByteCodeBreakpoints current_module
+ = entry (text "bytecode breakpoints") .
+ vcatOrNone .
+ map (uncurry (pprByteCodeBreakpoint current_module)) .
IntMap.toList
-- | Constructs textual information about a single bytecode breakpoint.
@@ -374,13 +378,13 @@ pprByteCodeBreakpoint :: Module -- ^ The enclosing module
-> Int -- ^ The index of the bytecode breakpoint
-> CgBreakInfo -- ^ The bytecode breakpoint
-> SDoc -- ^ The textual information
-pprByteCodeBreakpoint currentModule ix CgBreakInfo {..}
+pprByteCodeBreakpoint current_module ix CgBreakInfo {..}
= entry (text "bytecode breakpoint" <+> ppr ix) $
vcat [
- pprType $ cgb_resty,
- pprTypeVariables $ cgb_tyvars,
- pprVariables $ cgb_vars,
- pprCorrespondingSourceBreakpoint currentModule $ cgb_tick_id
+ pprType $ cgb_resty,
+ pprTypeVariables $ cgb_tyvars,
+ pprVariables $ cgb_vars,
+ pprCorrespondingSourceBreakpoint current_module $ cgb_tick_id
]
-- That the 'cgb_resty' field holds the type of the breakpoint is apparent
-- from the fact that this field is set by
@@ -426,20 +430,20 @@ pprCorrespondingSourceBreakpoint :: Module
-- ^ A reference to the source breakpoint
-> SDoc
-- ^ The textual information
-pprCorrespondingSourceBreakpoint currentModule
+pprCorrespondingSourceBreakpoint current_module
= entry (text "corresponding source breakpoint") .
- pprBreakpointID currentModule .
+ pprBreakpointID current_module .
either internalBreakLoc id
-- | Constructs textual information about the ID of a source breakpoint.
pprBreakpointID :: Module -- ^ The enclosing module
-> BreakpointId -- ^ The ID of the source breakpoint
-> SDoc -- ^ The textual information
-pprBreakpointID currentModule BreakpointId {..}
- | bi_tick_mod == currentModule = indexDoc
- | otherwise = indexDoc <+>
- text "in" <+>
- quotes (ppr bi_tick_mod)
+pprBreakpointID current_module BreakpointId {..}
+ | bi_tick_mod == current_module = indexDoc
+ | otherwise = indexDoc <+>
+ text "in" <+>
+ quotes (ppr bi_tick_mod)
where
indexDoc :: SDoc
@@ -470,7 +474,6 @@ pprActualHPCInfo ByteCodeHpcInfo {..}
pprTickBoxName $ bchi_tickbox_name,
pprTickCount $ bchi_tick_count
]
- where
-- | Constructs textual information about the hash of HPC info.
pprHPCInfoHash :: Int -> SDoc
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1758ebbafed11feda9247f2025ebbe…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1758ebbafed11feda9247f2025ebbe…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/sjakobi/T17088] testsuite: Run T17088 only with compacting GC
by Simon Jakobi (@sjakobi2) 21 Jul '26
by Simon Jakobi (@sjakobi2) 21 Jul '26
21 Jul '26
Simon Jakobi pushed to branch wip/sjakobi/T17088 at Glasgow Haskell Compiler / GHC
Commits:
95150960 by Simon Jakobi at 2026-07-21T18:39:00+02:00
testsuite: Run T17088 only with compacting GC
T17088 is a regression test for #17088, a pointer-tagging bug in the
compacting collector. Restore its original single-way scope, which was
lost when the test was converted to use the compacting_gc way.
The reproducer reads and prints an uninitialized byte array, so its
stdout is not stable. Ignore stdout while retaining checks for crashes
and other failures.
Closes #27534
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
1 changed file:
- testsuite/tests/rts/all.T
Changes:
=====================================
testsuite/tests/rts/all.T
=====================================
@@ -540,7 +540,11 @@ test('RestartEventLogging',
compile_and_run, ['RestartEventLogging_c.c'])
test('T17088',
- [extra_ways(['compacting_gc']), extra_run_opts('+RTS -A256k -RTS')],
+ [ only_ways(['compacting_gc'])
+ , extra_ways(['compacting_gc'])
+ , ignore_stdout # The test prints uninitialized memory. See #27534
+ , extra_run_opts('+RTS -A256k -RTS')
+ ],
compile_and_run, ['-rtsopts -O2'])
test('T15427', js_broken(22374), compile_and_run, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/95150960970efe46eae6b4c1f9a40d3…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/95150960970efe46eae6b4c1f9a40d3…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/andreask/deep-discounts-2026] doc fix
by Andreas Klebinger (@AndreasK) 21 Jul '26
by Andreas Klebinger (@AndreasK) 21 Jul '26
21 Jul '26
Andreas Klebinger pushed to branch wip/andreask/deep-discounts-2026 at Glasgow Haskell Compiler / GHC
Commits:
fd9855fa by Andreas Klebinger at 2026-07-21T16:32:06+00:00
doc fix
- - - - -
1 changed file:
- docs/users_guide/debugging.rst
Changes:
=====================================
docs/users_guide/debugging.rst
=====================================
@@ -943,6 +943,7 @@ parts that you are not interested in.
.. ghc-flag:: -dsuppress-guidance
:shortdesc: Suppress details of unfolding guidance.
:type: dynamic
+
:since: 10.2
Unfolding guidance describes how the structure of an argument impacts inlining
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/fd9855fa6e96f7ab472d754c411d535…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/fd9855fa6e96f7ab472d754c411d535…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/sjakobi/T17088] 44 commits: hadrian: fix HLS support
by Simon Jakobi (@sjakobi2) 21 Jul '26
by Simon Jakobi (@sjakobi2) 21 Jul '26
21 Jul '26
Simon Jakobi pushed to branch wip/sjakobi/T17088 at Glasgow Haskell Compiler / GHC
Commits:
ed261a7e by Cheng Shao at 2026-07-14T17:59:38-04:00
hadrian: fix HLS support
This patch fixes hadrian's HLS support so one can rely on HLS when
working on the hadrian codebase. Fixes #27480.
Not building/linking shared libraries for hadrian is a severely
premature optimization; this top-level setting in `cabal.project` only
affects home packages while the dependencies in the cabal store are
built with vanilla/dynamic anyway, and even adding dynamic builds to
home packages would not be costly due to cabal's usage of
`-dynamic-too`.
- - - - -
eee8ec5b by Cheng Shao at 2026-07-14T18:00:20-04:00
compiler: fix miscompiled %load_relaxed, add missing %store_relaxed
This patch fixes the %load_relaxed cmm primop compilation logic to
correctly use relaxed memory ordering, and adds the missing
%store_relaxed primop. Parsing logic of %load/%store with explicit
ordering is covered in the AtomicFetch test case. Fixes #27483.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
1718230f by Alan Zimmerman at 2026-07-14T18:01:06-04:00
EPA: Keep binds and sigs together in HsValBindsLR
We combine them into a single list for GhcPs, wrapped in the
ValBind data type, which is the bind equivalent of ValD, having
constructors for binds and sigs.
This simplifies exact print processing, especially when using it to
update the contents of local binds, as we no longer need AnnSortKey
BindTag
- - - - -
6bd1ad2a by Andreas Klebinger at 2026-07-14T18:01:49-04:00
Bump nofib submodule to account for MonoLocalBinds.
New versions of GHC enable MonoLocalBinds by default.
This breaks some of the benchmarks. I've fixed this and
this bump pulls in that fix.
- - - - -
7eb0f1c9 by Cheng Shao at 2026-07-14T18:02:31-04:00
testsuite: fix bytecodeIPE test under +ipe flavours
This patch fixes the bytecodeIPE test under +ipe flavours. It used to
fail under +ipe because the RTS is built with IPE info, then
stg_AP_info in RTS carries IPE info, so whereFrom wouldn't return
Nothing. Now the test checks IPE info of a datacon in the ghci-loaded
module which is not affected by whether the RTS is built with IPE info
or not. Fixes #27498.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
ef038aae by cydparser at 2026-07-15T04:35:41-04:00
Reduce bytes allocated for `capabilities` in RTS (fixes #27487)
In rts/Capability.c, `capabilities` is an array of pointers, but it was allocated as if it were an
array of Capability's.
- - - - -
d377e83e by Cheng Shao at 2026-07-15T04:36:27-04:00
rts: fix missing UNTAG in stg_readTVarIOzh
This patch fixes missing UNTAG on the current value closure read from
StgTVar. UNTAG is a no-op when it's stg_TREC_HEADER_info which is word
aligned; it may be a tagged closure, and reading info table from the
tagged address is an unaligned load which may cause issues on
platforms with strict alignment requirements.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
8ed03842 by Cheng Shao at 2026-07-15T04:36:27-04:00
rts: fix missing UNTAG in stg_control0zh_ll
This patch fixes missing UNTAG on the cont closure returned by
captureContinuationAndAbort. In case it's not NULL,
captureContinuationAndAbort returns a tagged StgContinuation closure,
in which case it must be untagged before accessing the
apply_mask_frame field.
In the past it worked out of luck: when apply_mask_frame was NULL then
mask_frame_offset is also 0 so the control flow didn't diverge to a
wrong path. Still, this is horribly wrong and will crash once
StgContinuation struct is refactored and fields are shuffled around.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
5aa7000a by Cheng Shao at 2026-07-15T04:37:08-04:00
compiler: fix redundant AP thunk codegen when not using -ticky-ap-thunk
This patch fixes a double negation confusion in !7525 that results in
some redundant AP thunk code generation when not using
-ticky-ap-thunk. Now, we use `stgToCmmUseStdApThunk` to indicate
whether precomputed AP thunks in the RTS should be used, which
defaults to `True`, unless `-ticky-ap-thunk` is passed.
`-finfo-table-map` now also implies `-ticky-ap-thunk`, since when
doing IPE profiling we want the generated AP thunks to be unique.
Fixes #27502.
-------------------------
Metric Decrease:
T3064
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
d43a7b7a by Brian McKenna at 2026-07-15T20:10:04+02:00
Strip ticks when desugaring bool guards
The special `considerAccessible` pattern was broken when compiling
with debug info. Compiling with debug info wraps expressions with
`SourceNote` ticks, which broke the internals of the
`desugarBoolGuard` function. Ticks are now ignored within this
function.
Fixes #27360
- - - - -
ede4b17b by Ben Gamari at 2026-07-15T22:59:53-04:00
base: Display ExceptionContext in WhileHandling's textual description
As originally-implemented the implementation for
`WhileHandling(displayExceptionAnnotation)` would display the
`ExceptionContext` of the exception which it carries (as this was the
behavior of `displayException`, in terms of which
`displayExceptionAnnotation` was implemented).
However, in 284ffab3 the definition of `SomeException(displayException)`
was changed to exclude the `ExceptionContext`. This means that
`WhileHandling(displayExceptionAnnotation)` fails to describe the
provenance of the exception which it captures, greatly limiting its
utility.
Return the implementation to its originally-specified behavior by
implementing `WhileHandling(displayExceptionAnnotation)` in terms of
`displayExceptionWithInfo`.
Fixes #27456.
- - - - -
0f64f348 by Cheng Shao at 2026-07-16T15:41:08+00:00
ci: add missing docker permission workaround in abi-test job
- - - - -
660cb239 by Cheng Shao at 2026-07-16T19:37:48+00:00
bindist: Fix make install -j race condition on macos/freebsd
This patch fixes make install -j race condition on macos/freebsd. BSD
install fails with EEXIST when multiple install processes concurrently
create the same prefix directory. So we add an `install_dirs`
prerequisite job that sequentially creates the directories for
subsequent jobs to work with. Fixes #27499.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
08130257 by Cheng Shao at 2026-07-16T19:37:48+00:00
ci: run bindist make install with -j
This patch makes the ci scripts run `make install` with `-j` to reduce
wall clock time when installing the bindist, see related issue for
benchmark numbers. This only affects ghc ci logic, the user-facing
default is up to distributors and is still `-j1`. Closes #27029.
- - - - -
d5ae6906 by Adam Gundry at 2026-07-17T04:57:43-04:00
Mark various language extension flags as deprecated (see #27329)
The following language extensions are now deprecated:
- AlternativeLayoutRule
- AlternativeLayoutRuleTransitional
- ParallelArrays
- PolymorphicComponents
- Rank2Types
In addition, the warning `-Walternative-layout-rule-transitional`
has been marked as deprecated, as it is emitted only under the
deprecated extension `XAlternativeLayoutRuleTransitional`.
- - - - -
fe3b059c by Andrew Lelechenko at 2026-07-17T04:58:26-04:00
base: re-export GHC.Environment.getFullArgs from System.Environment
CLC proposal https://github.com/haskell/core-libraries-committee/issues/431
- - - - -
722236dd by sheaf at 2026-07-18T08:48:31-04:00
Coercion optimisation: avoid double-Sym for InstCo
Ticket #27374 pointed out an issue with GHC.Core.Coercion.Opt.optCoercion's
handling of InstCo: it contravened (LC2) in Note [The LiftingContext in optCoercion]
because it applied the ambient 'sym' to a coercion that was then added
to the lifting context substitution.
Fixes #27374
Co-authored-by: Simon Jakobi <simon.jakobi(a)gmail.com>
- - - - -
ff70fc75 by sheaf at 2026-07-18T08:48:31-04:00
Coercion optimisation: avoid exponential behaviour
The change to coercion optimisation of 'InstCo' in the previous commit
introduces exponential behaviour to the coercion optimiser. To avoid
this, this commit provides a way to push in 'Sym' of an already-optimised
coercion: GHC.Core.Coercion.Opt.mkDeepSymCo.
See Note [Pushing Sym without re-optimising] in GHC.Core.Coercion.Opt.
- - - - -
dfef27f0 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Move THREADED_RTS-conditional struct members to end of Capability
Accessing members of the Capability struct from CMM code rely on
accessor macros. (The macros are generated by deriveConstants).
These macros have a single definition. This means that the offsets of
all struct members must *not* vary based on THREADED_RTS vs
!THREADED_RTS. This requires that any struct members that are
conditional on THREADED_RTS must occur after the unconditional struct
members. Hence we move all the ones that are conditional on
THREADED_RTS to the end.
Add a deriveConstants entry for the iomgr member of the Capability
struct, which was the motivation for this change.
Add warning messages to help our future selves. Debugging this took me
a couple hours in gdb!
- - - - -
c254e022 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Make the IOManager API use CapIOManager rather than Capability
This makes the API somewhat more self-contained and more consistent.
Now the IOManager API and each of the backends takes just the I/O
manager structure. Previously we had a bit of a mixture, depending on
whether the function needed access to the Capability or just the
CapIOManager.
We still need access to the cap, so we introduce a back reference to
reach the capability, via iomgr->cap.
Convert all uses in select and poll backends, but not win32 ones.
Convert callers in the scheduler and elsewhere.
Also convert the three CMM primops that call IOManager APIs. They just
need to use Capability_iomgr(MyCapability()).
- - - - -
4f3d8f31 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Split posix/MIO.c out of posix/Signals.c
The MIO I/O manager was secretly living inside the Signals file.
Now it gets its own file, like any other self-respecting I/O manager.
- - - - -
52ce04a9 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Rationalise some scheduler run queue utilities
Move them all to the same place in the file.
Make some static that were used only internally.
Also remove a redundant assignment after calling truncateRunQueue that
is already done within truncateRunQueue.
- - - - -
75bbdebc by Duncan Coutts at 2026-07-18T08:49:12-04:00
Rename initIOManager{AfterFork} to {re}startIOManager
These are more accurate names, since these actions happen after
initialisation and are really about starting (or restarting) background
threads.
- - - - -
724c0517 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Free per-cap I/O managers during shutdown and forkProcess
Historically this was not strictly necessary. The select and win32
legacy I/O managers did not maintain any dynamically allocated
resources. The new poll one does (an auxillary table), and so this
should be freed.
After forkProcess, all threads get deleted. This includes threads
waiting on I/O or timers. So as of this patch, resetting the I/O
manager is just about tidying things up. For example, for the poll
I/O manager this will reset the size of the AIOP table (which
otherwise grows but never shrinks).
In future however the re-initialising will become neeecessary for
functionality, since some I/O managers will need to re-initialise
wakeup fds that are set CLOEXEC.
- - - - -
c007d122 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Add a TODO to the MIO I/O manager
The direction of travel is to make I/O managers per-capability and have
all their state live in the struct CapIOManager. The MIO I/O manager
however still has a number of global variables.
It's not obvious how handle these globals however.
- - - - -
b65ab7b3 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Add a FIXME note in the Poll I/O manager
- - - - -
daf2bd6f by Duncan Coutts at 2026-07-18T08:49:12-04:00
Add missing updateRemembSetPushClosure in poll I/O manager
For the non-moving GC.
- - - - -
e33ca830 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Minor doc improvement to struct StgAsyncIOOp member outcome
Mention the enumeration names, as well as their numeric values. The rest
of the code uses the enum names.
- - - - -
4edd2579 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Minor doc improvements for StgTSOBlockInfo
Clarify that certain union members are used only by certain legacy
I/O managers. Hopefully we will be able to remove these at some point.
- - - - -
536bedbb by Duncan Coutts at 2026-07-18T08:49:12-04:00
Avoid exporting various win32-specific rts symbols
The BeginPrivate.h / EndPrivate.h scheme works perfectly well on
Windows, but all of the rts/win32/*.h files were not using it.
- - - - -
8139b5ac by Duncan Coutts at 2026-07-18T08:49:12-04:00
Remove wakeupIOManager, ioManagerWakeup and setIOManagerWakeupFd
We no longer need wakeupIOManager for the threaded RTS case, so we can
remove it and the bits only needed to support it. This includes the
pipe/eventfd fd shared between the RTS and the in-library I/O manager
used for waking up the I/O manager thread. The pipe/eventfd still
exists, but it no longer has to be communicated to the RTS, since the
RTS no longer needs to use it.
So we remove the RTS API export setIOManagerWakeupFd, and remove uses of
it within the I/O managers in ghc-internal.
- - - - -
74fe7c66 by Duncan Coutts at 2026-07-18T08:49:12-04:00
Add a new interruptIOManager API for the I/O managers
It will be used to interrupt awaitCompletedTimeoutsOrIO. Also update the
return type and docs for awaitCompletedTimeoutsOrIO to have it return
false when it gets interrupted, and have no useful post condition in
that case.
- - - - -
38792843 by Duncan Coutts at 2026-07-18T08:49:13-04:00
Add interruptIOManager support for select I/O manager
Uses the FdWakup mechanism.
- - - - -
2f3b00aa by Duncan Coutts at 2026-07-18T08:49:13-04:00
Add interruptIOManager support for poll I/O manager
Uses the FdWakup mechanism.
A quirk we have to cope with is that we now need to poll one more fd --
the wakeup_fd_r -- but this fd has no corresponding entry in the
aiop_table. This is awkward since we have set up our aiop_poll_table to
be an auxilliary table with matching indicies.
The solution this patch uses (and described in the comments) is to have
two tables: struct pollfd *aiop_poll_table, *full_poll_table;
and to have the aiop_poll_table alias the tail of the full_poll_table.
The head entry in the full_poll_table is the extra fd. So we poll the
full_poll_table, while the aiop_poll_table still has matching indicies
with the aiop_table.
Hurrah for C aliasing rules.
- - - - -
cee50131 by Duncan Coutts at 2026-07-18T08:49:13-04:00
Add interruptIOManager support for win32 legacy I/O manager
And remove unused related helper resetAbandonRequestWait. It is not
called because the event is created in auto-reset mode, so never needs
to be reset manually.
- - - - -
cf453143 by Duncan Coutts at 2026-07-18T08:49:13-04:00
Note lack of interruptIOManager support for WinIO I/O manager
Though there's a plausible design, we can't sanely test it at the moment
due to related WinIO bugs. Filed as issue #27403.
- - - - -
1b74a0ad by Duncan Coutts at 2026-07-18T08:49:13-04:00
Be more explicit about enum IOReadOrWrite values, and type within cmm
Belt and braces.
- - - - -
b388d093 by Brian McKenna at 2026-07-18T17:51:50-04:00
Ignore ticks in the pattern-match term oracle
The term-oracle in the pattern-match checker is keyed by a canonical
form of the scrutinee, computed by `makeDictsCoherent`. That canonical
form was tick-sensitive: two occurrences of an otherwise identical
expression that happened to carry different ticks were treated as
distinct values, breaking long-distance information.
This shows up in practice under `-finfo-table-map`, because the
desugarer wraps every record-selector use site in a `SourceNote`
carrying that site's span. For example:
data Box = Box { unBox :: Maybe Int }
f b = case unBox b of
Nothing -> 0
Just _ -> let Just x = unBox b in x
The two `unBox b` expressionss carry different SourceNote spans, the
pattern-match checker sees them as different, the long-distance
information from the outer `Just _` branch never reaches the
let-pattern, and `Just x = unBox b` is wrongly reported as
non-exhaustive.
We now strip all ticks in `makeDictsCoherent`. This is documented as
Wrinkle (UD1) of Note [Unique dictionaries in the TmOracle CoreMap].
Fixes #27314
- - - - -
c23e1acb by Mrjtjmn at 2026-07-18T17:52:45-04:00
Add explanations for unsolved Typeable constraints
This commit adds explanations for unsolved 'Typeable' constraints.
GHC will now provide additional explanations for an unsolved constraint
of the form 'Typeable ty', explain why GHC did not solve Typeable constraint.
e.g.:
- 'ty' is a polymorphic type (e.g. forall a. a -> a)
- 'ty' is a qualified type (e.g. Eq Int => Int)
- 'ty' is an unboxed sum type
- 'ty' is an unreduced type family application
- 'ty' whose kind is not typeable
Fixes #26532
- - - - -
cbef021e by Artem Pelenitsyn at 2026-07-19T07:49:55-04:00
ghc-internal: Lock.hs: fix typo and indentation
- - - - -
42918646 by Duncan Coutts at 2026-07-19T07:50:36-04:00
Fix failing test GcStaticPointers for non-moving GC
Minor mistake in asserting something before checking for that same
thing.
Specifically, Bdescr asserts HEAP_ALLOCED_GC, but Bdescr was being used
prior to a guard that checks HEAP_ALLOCED_GC. The solution is just to
move the use of Bdescr after the guard.
Thanks to Simon Jakobi for identifying the problem.
- - - - -
c2f6dcd4 by Sasha Bogicevic at 2026-07-20T10:31:56+02:00
Improve error messages for invalid record wildcards
Record wildcard hints are now shown in more contexts and include
constructor arity; matching with `..` on a fieldless constructor
now produces a dedicated error message.
Fixes #21101
- - - - -
4c02e76b by Duncan Coutts at 2026-07-21T10:37:21-04:00
Mark test T27105 as fragile, citing issue #27522
Scheduler fairness is fine, except when it isn't. And it isn't on CI
machines surprisingly often! See the issue for details.
- - - - -
ec8e8708 by Simon Jakobi at 2026-07-21T18:09:17+02:00
testsuite: Run T17088 only with compacting GC
T17088 is a regression test for #17088, a pointer-tagging bug in the
compacting collector. Restore its original single-way scope, which was
lost when the test was converted to use the compacting_gc way.
The reproducer reads and prints an uninitialized byte array. A debug RTS
fills freed memory, causing the output to differ from the normal RTS.
Ignore stdout for debug RTS builds while retaining the output check
elsewhere.
Closes #27534
Assisted-by: gpt-5.6-sol via Codex CLI
- - - - -
184 changed files:
- .gitlab-ci.yml
- .gitlab/ci.sh
- + changelog.d/21101
- + changelog.d/T26532
- + changelog.d/T27314.md
- + changelog.d/T27329
- + changelog.d/T27360
- + changelog.d/T27374
- + changelog.d/T27456
- + changelog.d/fix-cmm-atomic-load-store
- + changelog.d/fix-make-install-j
- + changelog.d/fix-use-std-ap-thunk
- compiler/GHC/Cmm/Parser.y
- compiler/GHC/Core/Coercion/Opt.hs
- compiler/GHC/Driver/Config/StgToCmm.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Pmc/Solver.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Parser/Annotation.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Env.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Rename/Names.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Rename/Utils.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/StgToCmm/Bind.hs
- compiler/GHC/StgToCmm/Config.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Instance/Typeable.hs
- compiler/GHC/Tc/Types/Rank.hs
- compiler/GHC/ThToHs.hs
- compiler/GHC/Types/GREInfo.hs
- compiler/GHC/Types/Hint.hs
- compiler/GHC/Types/Hint/Ppr.hs
- compiler/Language/Haskell/Syntax/Binds.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- docs/users_guide/expected-undocumented-flags.txt
- docs/users_guide/exts/rank_polymorphism.rst
- docs/users_guide/exts/static_pointers.rst
- ghc/GHCi/UI.hs
- hadrian/bindist/Makefile
- hadrian/cabal.project
- libraries/base/changelog.md
- libraries/base/src/System/Environment.hs
- libraries/base/tests/T15349.stderr
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Event/Control.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Manager.hs
- libraries/ghc-internal/src/GHC/Internal/Event/TimerManager.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Type.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle/Lock.hs
- libraries/ghc-internal/tests/backtraces/T14532b.stdout
- nofib
- rts/Capability.c
- rts/Capability.h
- rts/ContinuationOps.cmm
- rts/IOManager.c
- rts/IOManager.h
- rts/IOManagerInternals.h
- rts/PrimOps.cmm
- rts/RaiseAsync.c
- rts/RtsStartup.c
- rts/RtsSymbols.c
- rts/Schedule.c
- rts/Schedule.h
- rts/include/rts/IOInterface.h
- rts/include/rts/storage/Closures.h
- rts/include/rts/storage/TSO.h
- rts/posix/FdWakeup.h
- + rts/posix/MIO.c
- + rts/posix/MIO.h
- rts/posix/Poll.c
- rts/posix/Poll.h
- rts/posix/Select.c
- rts/posix/Select.h
- rts/posix/Signals.c
- rts/posix/Signals.h
- rts/posix/Timeout.c
- rts/posix/Timeout.h
- rts/rts.cabal
- rts/sm/NonMovingMark.c
- rts/win32/AsyncMIO.c
- rts/win32/AsyncMIO.h
- rts/win32/AsyncWinIO.h
- rts/win32/AwaitEvent.c
- rts/win32/AwaitEvent.h
- rts/win32/ConsoleHandler.h
- rts/win32/MIOManager.h
- rts/win32/ThrIOManager.h
- rts/win32/WorkQueue.h
- rts/win32/veh_excn.h
- testsuite/tests/backpack/should_compile/T13149.bkp
- testsuite/tests/cmm/should_run/AtomicFetch.hs
- testsuite/tests/cmm/should_run/AtomicFetch_cmm.cmm
- testsuite/tests/codeGen/should_run/cgrun025.stderr
- testsuite/tests/concurrent/should_run/T27105.hs
- testsuite/tests/concurrent/should_run/all.T
- + testsuite/tests/corelint/T27374.hs
- testsuite/tests/corelint/all.T
- testsuite/tests/determinism/determ017/A.hs
- testsuite/tests/exceptions/T26759.stderr
- testsuite/tests/ghc-e/should_fail/T18441fail7.stderr
- testsuite/tests/ghci/scripts/T12005.script
- testsuite/tests/ghci/scripts/bytecodeIPE.hs
- testsuite/tests/haddock/perf/Fold.hs
- testsuite/tests/indexed-types/should_fail/T7354.hs
- 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/layout/layout001.stdout
- testsuite/tests/layout/layout002.stdout
- testsuite/tests/layout/layout003.stdout
- testsuite/tests/layout/layout004.stdout
- testsuite/tests/layout/layout005.stdout
- testsuite/tests/layout/layout006.stdout
- testsuite/tests/layout/layout007.stdout
- testsuite/tests/layout/layout008.stdout
- testsuite/tests/layout/layout009.stdout
- testsuite/tests/linear/should_compile/T1735Min.hs
- testsuite/tests/mdo/should_fail/mdofail006.stderr
- testsuite/tests/parser/should_compile/DumpSemis.stderr
- + testsuite/tests/parser/should_compile/T13087.stderr
- testsuite/tests/parser/should_fail/T8431.stderr
- testsuite/tests/parser/should_fail/readFail038.stderr
- testsuite/tests/perf/compiler/T3064.hs
- + testsuite/tests/pmcheck/should_compile/T27314.hs
- + testsuite/tests/pmcheck/should_compile/T27360.hs
- testsuite/tests/pmcheck/should_compile/all.T
- testsuite/tests/polykinds/T7594.hs
- testsuite/tests/printer/Test20297.stdout
- testsuite/tests/programs/thurston-modular-arith/Main.hs
- + testsuite/tests/rename/should_fail/T21101.hs
- + testsuite/tests/rename/should_fail/T21101.stderr
- testsuite/tests/rename/should_fail/T9815.stderr
- testsuite/tests/rename/should_fail/T9815b.stderr
- testsuite/tests/rename/should_fail/T9815bghci.stderr
- testsuite/tests/rename/should_fail/T9815ghci.stderr
- testsuite/tests/rename/should_fail/all.T
- testsuite/tests/rts/all.T
- testsuite/tests/rts/ipe/IpeStats/Fold.hs
- testsuite/tests/runghc/T7859.stderr-mingw32
- testsuite/tests/simplCore/should_compile/T11562.hs
- testsuite/tests/simplCore/should_run/T3591.hs
- testsuite/tests/typecheck/should_compile/DeepSubsumption02.hs
- testsuite/tests/typecheck/should_compile/T12507.hs
- testsuite/tests/typecheck/should_compile/T13951.hs
- testsuite/tests/typecheck/should_compile/T18920.hs
- testsuite/tests/typecheck/should_compile/T2595.hs
- testsuite/tests/typecheck/should_compile/T7541.hs
- testsuite/tests/typecheck/should_fail/T15067.stderr
- + testsuite/tests/typecheck/should_fail/T26532.hs
- + testsuite/tests/typecheck/should_fail/T26532.stderr
- testsuite/tests/typecheck/should_fail/T6069.stderr
- testsuite/tests/typecheck/should_fail/T7368a.hs
- testsuite/tests/typecheck/should_fail/T9858b.stderr
- testsuite/tests/typecheck/should_fail/TcStaticPointersFail02.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_run/T1735_Help/Basics.hs
- testsuite/tests/typecheck/should_run/T3731-short.hs
- testsuite/tests/typecheck/should_run/T3731.hs
- testsuite/tests/typecheck/should_run/church.hs
- testsuite/tests/typecheck/should_run/tcrun008.hs
- testsuite/tests/typecheck/should_run/tcrun017.hs
- testsuite/tests/typecheck/should_run/tcrun026.hs
- testsuite/tests/typecheck/should_run/tcrun035.hs
- testsuite/tests/typecheck/should_run/tcrun036.hs
- utils/check-exact/ExactPrint.hs
- utils/check-exact/Main.hs
- utils/check-exact/Transform.hs
- utils/check-exact/Utils.hs
- utils/deriveConstants/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/877dff14a351b8d7c21cb65b133c3c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/877dff14a351b8d7c21cb65b133c3c…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
21 Jul '26
Simon Jakobi pushed new branch wip/sjakobi/T17088 at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/sjakobi/T17088
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 3 commits: Mark test T27105 as fragile, citing issue #27522
by Marge Bot (@marge-bot) 21 Jul '26
by Marge Bot (@marge-bot) 21 Jul '26
21 Jul '26
Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
4c02e76b by Duncan Coutts at 2026-07-21T10:37:21-04:00
Mark test T27105 as fragile, citing issue #27522
Scheduler fairness is fine, except when it isn't. And it isn't on CI
machines surprisingly often! See the issue for details.
- - - - -
31359457 by Recursion Ninja at 2026-07-21T11:39:28-04:00
Resolving many TTG related orphan type-class instances
This is part a technical debt removal effort made possible now
that separating out the AST via TTG has come to a close.
As the AST in 'L.H.S' has been incrementally separated from the GHC internals,
there are many accumulated orphan instance of 'Binary', 'NFData', 'Outputable',
and 'Uniquable'. The orphan instance of data-types from within 'L.H.S' have had
their orphan instances moved to either:
1. The module which defines the data-type
2. The module which defines the type-class;
i.e. moving an orphan 'Binary' instance to 'GHC.Utils.Binary'
Orphan instances resolved (37):
| Data-type | Resolved instance(s) | Former orphan module(s) |
| -------------------- | -------------------------- | ------------------------- |
| Role | Binary, NFData, Outputable | GHC.Core.Coercion.Axiom |
| SrcStrictness | Binary, NFData, Outputable | GHC.Core.DataCon |
| SrcUnpackedness | Binary, NFData, Outputable | GHC.Core.DataCon |
| Fixity | Binary, Outputable | GHC.Hs.Basic |
| FixityDirection | Binary, Outputable | GHC.Hs.Basic |
| LexicalFixity | Outputable | GHC.Hs.Basic |
| CCallTarget | NFData | GHC.Hs.Decls.Foreign |
| CType | NFData | GHC.Hs.Decls.Foreign |
| Header | NFData | GHC.Hs.Decls.Foreign |
| OverlapMode | Binary, NFData | GHC.Hs.Decls.Overlap |
| WithHsDocIdentifiers | NFData, Outputable | GHC.Hs.Doc |
| HsDocString | NFData | GHC.Hs.DocString |
| HsDocStringChunk | Binary, Outputable | GHC.Hs.DocString |
| HsDocStringDecorator | Binary, Outputable | GHC.Hs.DocString |
| NamespaceSpecifier | Outputable | GHC.Hs.ImpExp |
| ForAllTyFlag | Binary, NFData, Outputable | GHC.Hs.Specificity |
| Specificity | Binary, NFData | GHC.Hs.Specificity |
| PromotionFlag | Binary, Outputable | GHC.Types.Basic |
| FieldLabelString | Outputable, Uniquable | GHC.Types.FieldLabel |
| InlinePragma | Binary | GHC.Types.InlinePragma |
-------------------------
Metric Decrease:
hard_hole_fits
-------------------------
Closes #21262, #27469
- - - - -
c8ef4cb4 by Cheng Shao at 2026-07-21T11:39:28-04:00
rts: always use StgInt to represent cost center id
Currently cost center id is modeled as `Int` and it should be `StgInt`
uniformly in the RTS, hence this patch. Fixes #27524.
- - - - -
33 changed files:
- compiler/GHC/Core/Coercion/Axiom.hs
- compiler/GHC/Core/DataCon.hs
- compiler/GHC/Hs/Basic.hs
- compiler/GHC/Hs/Decls/Overlap.hs
- compiler/GHC/Hs/Doc.hs
- compiler/GHC/Hs/DocString.hs
- compiler/GHC/Hs/ImpExp.hs
- − compiler/GHC/Hs/Specificity.hs
- compiler/GHC/Parser/PostProcess.hs
- compiler/GHC/Types/Basic.hs
- compiler/GHC/Types/FieldLabel.hs
- compiler/GHC/Types/Fixity.hs
- compiler/GHC/Types/ForeignCall.hs
- compiler/GHC/Types/InlinePragma.hs
- compiler/GHC/Types/Unique.hs
- compiler/GHC/Types/Var.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/Language/Haskell/Syntax/Basic.hs
- compiler/Language/Haskell/Syntax/Decls/Foreign.hs
- compiler/Language/Haskell/Syntax/Doc.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- compiler/Language/Haskell/Syntax/ImpExp.hs
- compiler/Language/Haskell/Syntax/Specificity.hs
- compiler/ghc.cabal.in
- rts/Profiling.c
- rts/Trace.c
- rts/Trace.h
- rts/eventlog/EventLog.c
- rts/eventlog/EventLog.h
- testsuite/tests/concurrent/should_run/T27105.hs
- testsuite/tests/concurrent/should_run/all.T
- testsuite/tests/count-deps/CountDepsParser.stdout
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/bb3bf6f7abd607e5cadf4f0005b020…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/bb3bf6f7abd607e5cadf4f0005b020…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0
[Git][ghc/ghc][wip/fendor/external-unit-db-cache] Fixup: force UnitInfo to avoid retaining the old UnitInfo
by Hannes Siebenhandl (@fendor) 21 Jul '26
by Hannes Siebenhandl (@fendor) 21 Jul '26
21 Jul '26
Hannes Siebenhandl pushed to branch wip/fendor/external-unit-db-cache at Glasgow Haskell Compiler / GHC
Commits:
97fad109 by fendor at 2026-07-21T17:12:56+02:00
Fixup: force UnitInfo to avoid retaining the old UnitInfo
- - - - -
1 changed file:
- compiler/GHC/Unit/External/Index.hs
Changes:
=====================================
compiler/GHC/Unit/External/Index.hs
=====================================
@@ -301,7 +301,10 @@ updateWiredInUnitIndex wired_map pkgs unit_index = do
ui <- readUnitIndex unit_index
let
all_pkgs = updateWiredInUnits wired_map (ui_unitInfoMap ui) pkgs
- (new_pkgs, _pkgs_set) = partitionEithers all_pkgs
+ (new_pkgs', _pkgs_set) = partitionEithers all_pkgs
+ -- Make sure we force the 'UnitInfo' here.
+ -- Otherwise, we will retain a reference to the old 'UnitInfo'
+ new_pkgs <- traverse evaluateUnitInfoLists new_pkgs'
modifyUnitIndexCache unit_index (addUnitInfoMap $ mkUnitInfoMap new_pkgs)
pure (map (either id id) all_pkgs)
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/97fad109104262f5bf28581a38cec67…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/97fad109104262f5bf28581a38cec67…
You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help
1
0