Skip to content

pass: give transform passes a sanctioned way to replace and remove types #966

Closed

Description

@OmarAlJarrah

Problem

architecture.md §2.2 designs five transform passes: link, dedup, filter, version-slice and overlay. emitter-design §2.4 has the engine run version-slice before any emitter. At c387e25c none of them can be written as designed.

  • The registry rule refuses it. A pass that replaces or removes a type writes the type registry. TestRegistryWrites_StayInsideTheFramework refuses that outside compilers/compile and ir.
  • The sanctioned writer is out of reach. That writer is compile.Types, which pass/ may not import: archtest allows it ir only.
  • There is no copy helper. ir has no helper to copy a TypeDef, only ir.NewTypeDef. A throwaway pass that trims whitespace from Docs.Summary needed reflect to rebuild each type.
  • The rule is easy to dodge. It is syntactic: out.Types[id] = … is flagged, while maps.Clone into a local variable and a write through that variable is not.

The engine side is fixed as well:

  • the pass list is defaultPasses;
  • engine.NewWith takes compilers only, so an embedder cannot add a pass;
  • two tests pin the exact list (engine/passes_test.go, cmd/morphic/validate_test.go);
  • the typed per-pass settings and the passes that cannot be disabled, both decided in §2.2, have no mechanism yet.

Direction

A proposal:

  • An ir-level copy-on-write editor. For example, ir.Edit(doc) returns a builder whose ReplaceType, RemoveType and Done produce a new Document sharing what was not touched, and keep invariant 3's one node per ID.
  • ir already owns the registry, so the editor needs no new owner. The archtest rule then names the editor as the way in for passes.
  • engine.NewWith accepts passes for embedders, and the pinned-list tests read the list rather than repeating it.
  • The required-pass mechanism lands with the first pass that needs it.

Done when a filter pass that removes an unused type is written without reflect and without tripping the registry rule.

Out of scope

Any particular transform. Usage may not need a pass at all (#950).

Related: #950, #689

Priority: P3, rule 3 (off the golden spec: no transform changes what it compiles to today; a later emitter needs version-slice and filter). A pass writing out.Types[id] → TestRegistryWrites_StayInsideTheFramework fails (morphic @c387e25c).

Activity

  1. added
    type:featureNew capability or enhancement
    priority:P3Later emitters, M4 and up, 3.2-only, streaming, webhooks, rare constructs
    on Oct 19, 2026
  2. OmarAlJarrah commented on Oct 20, 2026

    @OmarAlJarrah
    MemberAuthor

    Once #1001 merges, the registry rule this issue describes moves out of internal/archtest. TestRegistryWrites_StayInsideTheFramework becomes the ruleguard rule registryWrites in internal/lintrules/rules.go. golangci-lint runs it, and make lint-planted holds it to planted findings.

    Two parts of the Problem change with it:

    • "The rule is easy to dodge." No longer true. The rule matches types, not spellings, so it refuses:
      • maps.Clone of a registry;
      • a write through a local variable;
      • an aliased ir import;
      • make, a conversion, delete, clear, maps.Copy/Insert/DeleteFunc;
      • a write in a multiple assignment or a range clause.
    • "The registry rule refuses it." Still true. A pass writing out.Types[id] now fails lint instead of the test, so the probe in the Priority line becomes make lint-planted.

    For the Direction: the ir editor sits in package ir, which the rule already exempts as an owner, so it needs no new exemption.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority:P3Later emitters, M4 and up, 3.2-only, streaming, webhooks, rare constructstype:featureNew capability or enhancement

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions