Skip to content

Store closed named occurrences module-locally and index program representatives - #12704

Merged
rtfeldman merged 3 commits into
mainfrom
issue-12693-stored-closed-occurrences
Oct 29, 2026
Merged

rtfeldman merged 3 commits into
mainfrom
issue-12693-stored-closed-occurrences

Conversation

@rtfeldman

@rtfeldman rtfeldman commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #12693. Since #12659, lowering gives every closed named type one representative checked occurrence per program (the declaring module's when it holds one, otherwise the lowest-keyed module's), and the constant-store writer persisted that occurrence into the storing module's cache entry. When a package was checked from one app, the representative could be that app's own module, so a later build of another app reusing the package's entry restored a named type whose ty_module named a module outside its program and hit the "persistent named occurrence has no checked artifact" invariant while recording a persistent interface summary. The writer now rebinds every closed named occurrence to one the storing module's identity covers: the storing module's own occurrence of the same checked type key, or, for a stored closure's captures lowered in the callee's module, the occurrence in the lowest-keyed module of the storing module's transitive imports that holds one. Stored-type restoration resolves each occurrence back to the current program's representative so restored and freshly lowered types remain one Monotype.

The representative itself now comes from an index the coordinator builds once from every module view's named closed root rows and shares read-only with workers, in place of the per-builder lazy scan over all module views for each distinct closed key.

…sentatives

A checked module's ConstStore persisted the Monotype named type of each
stored constant as lowered, and since #12659 a closed named type's
occurrence is one representative per program: the declaring module's
occurrence when it holds one, else the lowest-keyed module's. That module
can be the app the package was checked from, so a later program reusing
the package's cache entry found no such module and `roc build` hit the
"persistent named occurrence has no checked artifact" invariant while
recording a persistent interface summary (#12693).

The constant-store writer now rebinds every closed named occurrence to
the storing module's own occurrence of the same canonical key, so an
entry names only modules its identity covers, and stored-type
restoration canonicalizes each occurrence back to the current program's
representative, so restored and freshly lowered types stay one Monotype.

The representative itself now comes from an index built once on the
coordinator from every module view's named closed root rows and borrowed
by workers, replacing the per-builder lazy scan over all module views
for each distinct closed key.
The constant-store writer keeps the storing module rather than a snapshot
of its checked type view, compares module keys as arrays, and the design
text and field docs use the checked type key and checked module cache
entry vocabulary.
A stored closure's captures are lowered in the callee's module, so their
closed named types need not occur in the storing module's own checked
types. The writer now rebinds such an occurrence to the lowest-keyed
module of the storing module's transitive imports that holds one, which
the storing module's identity covers, and the regression fixture stores a
closure capturing an `Api` nominal that `Form` never mentions.
@rtfeldman
rtfeldman marked this pull request as ready for review October 29, 2026 18:44
@rtfeldman
rtfeldman merged commit c8c900e into main Oct 29, 2026
50 checks passed
@rtfeldman
rtfeldman deleted the issue-12693-stored-closed-occurrences branch October 29, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant