Skip to content

Resolve receiver method registration collisions - #10745

Merged
lukewilliamboswell merged 1 commit into
roc-lang:mainfrom
lukewilliamboswell:fix/duplicate-method-registration
Aug 13, 2026
Merged

Resolve receiver method registration collisions#10745
lukewilliamboswell merged 1 commit into
roc-lang:mainfrom
lukewilliamboswell:fix/duplicate-method-registration

Conversation

@lukewilliamboswell

Copy link
Copy Markdown
Collaborator

Problem

A receiver can have both a method declared in its own associated block and a receiver extension declared in an empty nominal namespace. Canonicalization appended both registrations under the same (receiver owner, method name) key. Unique method-table finalization therefore trapped in release builds and reported this invariant in Debug builds:

SortedArrayBuilder invariant violated: duplicate key reached unique finalization

RocRay reproduces this with Program.Update.map/map2 and the corresponding Program.map/map2 namespace extensions. This prevented RocRay from updating to nightly-2026-08-12-606470f.

Fix

Canonicalization now owns construction-time collision policy explicitly:

  • A method declared by its receiver takes precedence over a namespace receiver extension, independently of source order.
  • Both qualified functions remain available.
  • Two receiver extensions retain the existing source-order shadowing diagnostic and explicitly replace the earlier dispatch entry.
  • Declaration-owned duplicates remain a producer invariant because the associated-value duplicate check owns that source error.

ModuleEnv appends and replaces the parallel method identity/definition entries atomically, so unique finalization remains a strict invariant rather than silently deduplicating malformed producer output.

The focused regression covers both declaration orders and verifies qualified calls plus receiver dispatch.

This extracts the focused method-registration work from #10717. The later Fix parallel MiniCI failures commit from that PR was audited but intentionally not included: it also depends on broad evaluator, Boxy, host-effect, and Monotype changes from the rest of #10717, while this focused branch passes MiniCI unchanged.

Validation

On the original nightly base (606470f):

  • zig build minici: 75/75 phases passed
  • Focused CLI regression: passed all 4 tests
  • zig build run-test-zig-module-can
  • Zig lint, tidy, formatting, test-wiring, and git diff --check gates
  • RocRay: 17/17 examples passed roc check, roc fmt --check, and roc test
  • RocRay glue generation completed successfully

After rebasing onto current main (446d128 at validation time):

  • Focused CLI regression passed
  • zig build run-test-zig-module-can passed
  • Zig lint, tidy, test-wiring, and git diff --check gates passed

A full current-main RocRay sweep is independently blocked by roc-random 0.9.0 using APIs/inference that changed after the August 12 nightly (Iter.rev and numeric shift inference); the method-registration failure itself remains fixed.

@lukewilliamboswell

Copy link
Copy Markdown
Collaborator Author

End-to-end RocRay validation is now complete against a locally built nightly-equivalent compiler: source commit 606470f plus this PR's focused commit, built ReleaseFast with -Dcompiler-version=nightly-2026-08-12-606470f.

The full roc-ray-elm suite passed without skips:

  • Platform zig build
  • Compiler ABI regeneration from immutable 606470f glue source
  • 17/17 roc check
  • 17/17 roc fmt --check
  • 17/17 roc test
  • 17/17 optimized native roc build
  • 17/17 three-frame headless runtime smoke tests
  • CLI argument integration probe
  • Types and platform bundle creation
  • 17/17 builds against the served bundle URL
  • Wayland platform bundle creation and URL build

This also confirms the published-nightly failure mode: the unpatched ReleaseFast compiler traps with SIGILL at unique method-table finalization; with this producer-side collision policy applied, glue generation and the entire application/package lifecycle complete successfully.

The generated RocRay ABI changed as expected for the newer compiler (including the erased-callable ABI), and the existing host changes in that RocRay worktree compile and pass runtime smoke coverage with it.

@lukewilliamboswell
lukewilliamboswell marked this pull request as ready for review August 12, 2026 23:12
@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR moves receiver-method collision handling into canonicalization so receiver-owned declarations consistently take precedence over namespace extensions without producing duplicate finalized keys.

  • Tracks each dispatch registration’s origin and construction-time table position.
  • Atomically appends or replaces parallel method identity and definition entries.
  • Preserves source-order shadowing behavior between competing receiver extensions.
  • Adds a CLI regression covering both declaration orders, qualified calls, and receiver dispatch.

Confidence Score: 5/5

The PR appears safe to merge; no concrete blocking or independently actionable non-blocking issue was identified.

The collision policy covers both registration orders, paired method-table mutations preserve key alignment before finalization, and the focused regression verifies dispatch and qualified-call behavior.

Important Files Changed

Filename Overview
src/canonicalize/Can.zig Introduces construction-time registration provenance and explicit, source-order-independent collision handling for receiver dispatch.
src/canonicalize/ModuleEnv.zig Adds paired append and indexed replacement operations that keep method identity and definition tables synchronized.
src/cli/test/parallel_cli_runner.zig Wires the receiver-method precedence regression into the parallel CLI suite.
test/cli/ReceiverMethodDeclarationPrecedence.roc Verifies qualified functions remain callable and receiver declarations win in both source orders.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Associated method discovered] --> B[Build receiver-owner and method-name key]
    B --> C{Existing registration?}
    C -- No --> D[Append identity and definition entries]
    C -- Yes --> E{Existing and new kinds}
    E -- Declaration then extension --> F[Keep declaration]
    E -- Extension then declaration --> G[Replace entry with declaration]
    E -- Extension then extension --> H[Emit shadowing diagnostic]
    H --> I[Replace entry with later extension]
    D --> J[Finalize unique sorted method tables]
    F --> J
    G --> J
    I --> J
Loading

Reviews (1): Last reviewed commit: "Resolve receiver method and alias reques..." | Re-trigger Greptile

@lukewilliamboswell
lukewilliamboswell merged commit b82fa0e into roc-lang:main Aug 13, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant