Skip to content

feat(ir): throws is Vec<u16> — schema-global error ordinals, cross-schema - #47

Merged
Kinflou merged 1 commit into
masterfrom
feat/ir-throws-error-ordinals
Sep 1, 2026
Merged

feat(ir): throws is Vec<u16> — schema-global error ordinals, cross-schema#47
Kinflou merged 1 commit into
masterfrom
feat/ir-throws-error-ordinals

Conversation

@Kinflou

@Kinflou Kinflou commented Sep 1, 2026

Copy link
Copy Markdown
Member

The 4th core ↔ target IR change (docs Design §4.4). Function.throws goes from Vec<String> (bare names) to Vec<u16> (schema-global error ordinals), resolved at freeze. Follows #46.

The error space

plan_error_space runs before the main freeze loop:

  • Locally-declared errors take ordinals 0..N in declaration order.
  • Each distinct ! Name a function throws that isn't local is appended as a re-exported import: resolved through the schema's in-scope uses (when there's a ProjectContext) to the foreign error decl, which is frozen into this schema's stream with imported_from: Some(<ns>). Unresolvable names still get a stable slot, marked imported_from: Some("<unresolved: Name>").

Every ! Name ends up a u16, and a cross-schema throw keeps a single-u16 wire id — the design's "re-export slot in the importing schema's ordinal space".

FrozenUnit::Error

Two new fields:

field
ordinal: u16 the slot — what travels in the envelope's err id. Explicit, not stream position, so a local error declared after a protocol still has a stable id.
imported_from: Option<String> None = local; Some(ns) = a re-export (or <unresolved: Name>).

Append-only discipline (retire in place, never reorder/reuse) is the author's to keep; version-diff enforcement of it is a separate follow-up — same as Error fields/message not being diffed yet.

Not in scope

  • Multiple throws per function (! A, B) — grammar is still single ! Name; Vec<u16> is 0-or-1 today, forward-compatible.
  • Errors as general importable symbols (glob-expansion, validator) — this resolves them only for throws, via a local walk of the uses, without touching schema_declares_symbol or the validator.

Tests

incremental + imports: local ordinal assignment; an unresolved throw gets a marker slot; a foreign used error gets a re-export slot after the locals with its fields/message carried over; the function points at the right ordinal. Full core suite green — 247 passed, 0 failed.

Downstream

FrozenUnit shape change → one coordinated comline-core rev-bump across generation / cli / comline-{rust,typescript} when this + #46 land (they only match Function / Error with .., so rev-bump, not code changes).

…hema

The 4th core-target-contract IR change (docs Design 4.4). `Function.throws`
goes from `Vec<String>` (bare names) to `Vec<u16>` (schema-global error
ordinals), resolved at freeze.

## The error space

`plan_error_space` runs before the main freeze loop:

- Locally-declared `error`s take ordinals 0..N in declaration order.
- Each distinct `! Name` a function throws that isn't local is appended as a
  re-exported import: resolved through the schema's in-scope `use`s (when
  there's a ProjectContext) to the foreign `error` decl, which is frozen into
  this schema's stream with `imported_from: Some(<ns>)`. Unresolvable names
  still get a stable slot, marked `imported_from: Some("<unresolved: Name>")`.

So every `! Name` ends up a `u16`, and cross-schema throws keep a single-u16
wire id -- the design's "re-export slot in the importing schema's ordinal
space".

## FrozenUnit::Error

Two new fields: `ordinal: u16` (the slot -- what travels in the envelope's
`err` id) and `imported_from: Option<String>` (`None` local, `Some(ns)` a
re-export). The ordinal is explicit rather than stream position, so a local
`error` declared after a `protocol` still has a stable id.

Append-only discipline (retire in place, never reorder/reuse) is the author's
to keep; version-diff enforcement of it is a separate follow-up, same as
Error fields/message not being diffed yet.

## Not in scope

- Multiple throws per function (`! A, B`) -- grammar is still single `! Name`;
  `Vec<u16>` is 0-or-1 today, forward-compatible.
- Errors as general importable symbols (glob-expansion, validation) -- this
  resolves them only for `throws`, via a local walk of the `use`s, without
  touching `schema_declares_symbol` / the validator.

## Tests

`incremental` + `imports`: local ordinal assignment, an unresolved throw gets
a marker slot, a foreign `use`d error gets a re-export slot after the locals
with its fields/message carried over, and the function points at the right
ordinal. Full core suite green (247 passed).

## Downstream

`FrozenUnit` shape change -> coordinated `comline-core` rev-bump across
generation / cli / comline-{rust,typescript} when this + core#46 land (they
only match `Function` / `Error` with `..`, so rev-bump not code).
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