Skip to content

Build the hosted catalog from the platform header's hosted section - #10828

Merged
rtfeldman merged 1 commit into
mainfrom
issue-10809/hosted-catalog-from-section
Aug 17, 2026
Merged

Build the hosted catalog from the platform header's hosted section#10828
rtfeldman merged 1 commit into
mainfrom
issue-10809/hosted-catalog-from-section

Conversation

@rtfeldman

@rtfeldman rtfeldman commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

A platform header's hosted section is the complete list of functions the host supplies, and it is what gives each one its linker symbol and its host dispatch slot. Three stages nevertheless built their own hosted catalog by scanning every hosted declaration in scope and then asserting that the scan agreed with the checked hosted binding table, so any platform whose section did not line up with its declarations aborted the compiler rather than reporting the section. A declaration the section omits aborted post-check lowering with platform hosted binding count 1 disagrees with hosted catalog size 2; a section naming one declaration twice aborted the same way with the counts reversed, and aborted the roc <app> run path and --specialize=no lowering through their own copies of that assertion. All three now build from the bindings, so the section decides how many dispatch slots exist and which declaration occupies each one — naming one declaration twice is two slots, which is what the header asked for and what checking already reports as a duplicate. Lowering without specialization consumes those bindings too, rather than re-deriving the section by matching declaration names against the header's text.

A declaration the section omits then has no catalog entry at all, which is right, since it has no symbol to call and no slot to occupy. A program that called one went on to abort with hosted procedure template was not output in the hosted catalog, so the checked-modules-to-LIR entrance now refuses a program that still carries such a declaration; checking already reports it, so the compile has failed by the time lowering starts and refusing there costs no diagnostic. Compile-time finalization lowers a module whose own checking has not finished, and such a module has no bindings yet, so that entrance reads nothing into their absence there.

That refusal is only sound if checking reports every declaration it covers, and one shape went unreported: a section entry names its target through an import, so no entry can reach a declaration written in the platform root itself, yet checking walked only the modules the root owns. A hosted declaration in main.roc therefore passed roc check cleanly and was stopped later with nothing to say. The root is now checked against the section alongside the modules it owns. Glue reads the same section to name each hosted function's symbol and aborted on the same input; it renders the platform's diagnostics already and now stops on them, because a platform checking rejected has no declared surface for glue to emit.

A platform header's hosted section is the complete list of functions the
host supplies, and it is what gives each one its linker symbol and its
host dispatch slot. Three stages nevertheless built their own hosted
catalog by scanning every hosted declaration in scope and then asserting
that the scan agreed with the checked hosted binding table, so a platform
whose section did not line up with its declarations aborted the compiler
instead of reporting the section. A declaration the section leaves out
aborted post-check lowering with `platform hosted binding count 1
disagrees with hosted catalog size 2`; a section naming one declaration
twice aborted the same way with the counts reversed, and aborted the
`roc <app>` path and `--specialize=no` lowering through their own copies
of the same assertion.

All three now build from the bindings, so the section decides how many
dispatch slots exist and which declaration occupies each one. Naming one
declaration twice is two slots, which is what the header asked for and
what checking reports as a duplicate. Lowering without specialization
reads those bindings too, in place of re-deriving the section by matching
declaration names against the header's text.

A declaration the section leaves out then has no catalog entry, which is
right—it has no symbol to call and no slot to occupy—but a program that
called one went on to abort with `hosted procedure template was not
output in the hosted catalog`. The checked-modules-to-LIR entrance now
refuses a program that still carries such a declaration. Checking already
reports it against the section it is missing from, so the compile has
failed by the time lowering starts and refusing costs no diagnostic.
Compile-time finalization lowers a module whose own checking has not
finished, and such a module has no bindings yet, so that entrance reads
nothing into their absence there.

For that refusal to be sound, checking has to report every declaration it
covers. A section entry names its target through an import, so no entry
can reach a declaration written in the platform root itself, and checking
walked only the modules the root owns—leaving a hosted declaration in
`main.roc` unreported, accepted by `roc check`, and stopped later with
nothing to say. The root is now checked against the section alongside the
modules it owns.

Glue reads the same section to name each hosted function's symbol and
aborted with `hosted function 'Host.unlisted' has no platform hosted
symbol` for the same input. It renders the platform's diagnostics already
and now stops on them, because a platform checking rejected has no
declared surface for glue to emit.
@rtfeldman
rtfeldman force-pushed the issue-10809/hosted-catalog-from-section branch from 3370f93 to 1f3b43a Compare August 16, 2026 22:28
@rtfeldman
rtfeldman marked this pull request as ready for review August 17, 2026 01:09
@rtfeldman
rtfeldman merged commit e59561c into main Aug 17, 2026
20 of 21 checks passed
@rtfeldman
rtfeldman deleted the issue-10809/hosted-catalog-from-section branch August 17, 2026 01:10
@greptile-apps

greptile-apps Bot commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR makes the checked platform header’s hosted bindings authoritative for hosted catalogs and prevents lowering or glue generation from consuming unbound hosted declarations.

  • Builds CLI, boxy, and monotype hosted catalogs from checked bindings, preserving section order, symbols, and duplicate slots.
  • Extends platform checking to report hosted declarations in the platform root.
  • Adds a checked-to-LIR boundary error for hosted declarations omitted from the section and propagates it through compiler callers.
  • Makes glue stop after rejected platform checking and adds regression coverage for omitted, duplicated, and root-level hosted declarations.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete blocking or independently actionable non-blocking defect established in the changed behavior.

The hosted catalogs consistently derive their entries, symbols, and dispatch order from checked bindings, while invalid omitted or duplicate declarations are reported and stopped before unsupported lowering or glue output proceeds.

Important Files Changed

Filename Overview
src/check/Check.zig Refactors hosted-declaration collection and includes the platform root when checking declarations against the hosted section.
src/lir/checked_pipeline.zig Adds the checked-to-LIR guard that rejects hosted procedures absent from the visible platform binding table.
src/postcheck/boxy/lower.zig Rebuilds the boxy hosted catalog from checked bindings rather than reconciling a declaration scan with header text.
src/postcheck/monotype/lower.zig Rebuilds the monotype hosted catalog in binding order, preserving each binding’s symbol and dispatch slot.
src/cli/main.zig Applies checked bindings by replacing the scanned CLI hosted catalog and propagates the new lowering error.
src/glue/glue.zig Stops glue generation after platform checking errors and handles unbound-hosted lowering failures without panicking.
src/eval/compile_time_finalization.zig Preserves compile-time finalization behavior by lowering with the checking-finalization state and treating unexpected binding rejection as an invariant failure.
src/cli/test/parallel_cli_runner.zig Adds regression coverage for omitted declarations, duplicate entries, platform-root declarations, run/no-specialize paths, and glue diagnostics.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Platform hosted section] --> B[Checker resolves HostedBindingTable]
    B --> C{Checking diagnostics?}
    C -->|Errors| D[Stop build or glue]
    C -->|Valid| E[Checked-to-LIR boundary]
    E --> F{Every hosted procedure bound?}
    F -->|No| G[HostedFunctionNotBound]
    F -->|Yes| H[Build catalog in binding order]
    H --> I[Assign linker symbols and dispatch slots]
    I --> J[Boxy, monotype, or CLI lowering]
Loading

Reviews (1): Last reviewed commit: "Build the hosted catalog from the platfo..." | Re-trigger Greptile

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