§03 Typeck — capset expansion + validation
Goal
Resolve every capset reference in uses clauses to its expanded capability set, before type checking proper. Reject cycles, invalid members, and visibility violations.
Implementation Sketch
Capset resolution is name resolution, not type checking — capsets have no runtime representation and are not types. The expansion lives in a pre-pass that walks the module’s declarations:
- Collect
CapsetDeclnodes into a per-moduleCapsetRegistry { name → Vec<Name> }(compiler_repo/compiler/ori_types/src/check/registration/). - Compute the transitive closure for each capset via topological sort. Cycles surface here (E1222).
- Walk every
usesclause in the module. Replace each member that is a capset name with its expanded list; deduplicate. - Validate each member resolves to either a capability trait OR another capset (E1223 for non-capability/non-capset members). Validate
pubcapsets only referencepubmembers (E1224). - Erase capset references from the typed IR — by the time
ori_canonconsumes the module, no capset name remains anywhere.
This matches Koka’s effect-alias model (see proposal Prior Art) — aliases are expanded during name resolution, never reach the type checker.
Implementation Items
- Create
compiler_repo/compiler/ori_types/src/check/registration/capsets.rs—register_capsets(module) -> CapsetRegistry. -
CapsetRegistry::expand(name) -> Result<Vec<Name>, CapsetError>— transitive closure with cycle detection (DFS + visited set + on-stack set). - Hook into the existing
uses-clause walker (compiler_repo/compiler/ori_types/src/check/capabilities/orcompiler_repo/compiler/ori_types/src/check/registration/capabilities.rs— locate viascripts/intel-query.sh callers register_uses_clause --repo orior similar). - Emit E1221 (empty capset) at registration time — declarations with
members: []. (Could be parser-side; pick ONE site.) - Emit E1222 (cycle) when DFS hits an on-stack node.
- Emit E1223 (invalid member) when a member resolves to neither a capability trait nor another capset.
- Emit E1224 (visibility) when a
pub capsetreferences a non-pubmember. - Emit E1225 (or reuse E12xx) for capset/trait/type name collisions in the same scope.
- Verify capsets are gone from the typed IR: walk a module post-typeck, assert no
Tag::Namedwith a name that appears inCapsetRegistry. - Rust Tests:
compiler_repo/compiler/ori_types/src/check/registration/capsets/tests.rs— single capset, transitive (3-level), cycle, empty, non-capability member, visibility violation, name collision, mixed-with-capabilitiesusesclause. - Phase audit: update
compiler_repo/.claude/rules/typeck.mdif a new rule anchor is needed for capset expansion (likelyCP-Nin the capabilities section).
Spec References
- Proposal §Expansion + §Validation.
- Spec
20-capabilities.md §20.11. typeck.md §CP-*capabilities-checker rules — capset expansion lands as a new rule (CP-N).
Tests
- Rust unit tests in this section.
- Spec tests owned by §05 (cycle, visibility, transitive, mixed).
Intelligence Reconnaissance
scripts/intel-query.sh similar "expand_alias" --repo koka,rust,swift --limit 5 for prior-art expansion patterns. scripts/intel-query.sh callers check_uses_clause --repo ori for the integration site. scripts/intel-query.sh file-symbols "compiler_repo/compiler/ori_types/src/check/registration/" --repo ori to map siblings.
Diagnostics co-development
E1221 / E1222 / E1223 / E1224 / E1225 are owned jointly with §04 — the validation rules ARE the diagnostics. Both sections land together. Test failures detected here automatically exercise §04’s error path.