0%

Section 5: Type Declarations

Goal: User-defined types

SPEC: spec/08-types.md, spec/09-properties-of-types.md, spec/10-declarations.md

Status: In-progress — Structs (5.1), sum types (5.2), newtypes (5.3), generics (5.4), built-in generics (5.6), derive (5.7), visibility (5.8), associated functions (5.9) all working in evaluator and AOT. Compound type inference (5.5) entirely pending. AOT coverage exists for structs, sum types, tuples, and all 7 derivable traits. Verified 2026-03-29.

SYNC POINT: Adding a new built-in type (e.g., Duration, Size, CPtr, Nursery) requires updates across ori_ir (type variant), ori_types (registration + method signatures), ori_eval (runtime representation + method dispatch), ori_llvm (type layout + codegen), and library/std/ (prelude or module definitions). This section primarily covers user-defined types, but built-in types added by other sections (11, 16, 17, 18) follow the same pattern.


5.1 Struct Types


  • Implement: Parse type Name = { field: Type, ... } — spec/08-types.md § Struct Types, spec/10-declarations.md § Type Declarations

    • Rust Tests: ori_parse/src/tests/parser.rs, ori_parse/src/tests/compositional.rs — struct parsing tests
    • Ori Tests: tests/spec/declarations/struct_types.ori (35+ tests: basic, single field, empty, nested, many fields, mixed types, generic, shorthand, spread, with Option/List/Tuple/Function fields)
  • Implement: Register struct in type environment — spec/10-declarations.md § Type Declarations

    • Rust Tests: ori_types/src/check/registration/ — type registry tests (implicit in all struct tests)
    • Ori Tests: All struct tests verify type registration
  • Implement: Parse struct literals Name { field: value } — spec/08-types.md § Struct Types

    • Rust Tests: ori_parse/src/tests/parser.rstest_struct_literal_in_expression, test_struct_literal_in_if_then_body, test_if_condition_disallows_struct_literal (negative pin)
    • Ori Tests: tests/spec/declarations/struct_types.ori — all tests create struct literals
  • Implement: Type check struct literals — spec/08-types.md § Struct Types

    • Rust Tests: ori_types/src/infer/ — struct literal type checking
    • Ori Tests: tests/spec/declarations/struct_types.ori
    • AOT Tests: ori_llvm/tests/aot/structs.rs — 30 tests passing (struct construction with int/bool/str/mixed fields, update syntax, nested structs, function params/returns, closures, derived Eq)
  • Implement: Shorthand Point { x, y } — spec/08-types.md § Struct Types

    • Rust Tests: ori_parse/src/grammar/postfix.rs — shorthand parsing
    • Ori Tests: tests/spec/declarations/struct_types.oritest_shorthand_init, test_mixed_shorthand
    • AOT Tests: No AOT coverage yet — ori_llvm/tests/aot/structs.rs does not test shorthand syntax specifically
    • WEAK TESTS: Only int types tested in shorthand. Missing str/bool shorthand coverage.
  • Implement: Field access — spec/08-types.md § Struct Types

    • Rust Tests: ori_types/src/infer/ — field access type inference
    • Ori Tests: tests/spec/declarations/struct_types.ori — field chaining (c.ceo.name, deep nesting)
    • AOT Tests: ori_llvm/tests/aot/structs.rs — all 30 tests exercise field access; nested field chains in test_struct_nested_basic, test_struct_nested_three_levels
  • Implement: Destructuring — spec/14-expressions.md § Destructuring

    • Rust Tests: Parser in ori_parse/src/grammar/expr/primary.rsparse_binding_pattern()
    • Ori Tests: tests/spec/declarations/struct_types.oritest_destructure, test_destructure_partial, test_destructure_rename
    • AOT Tests: No AOT coverage yet — ori_llvm/tests/aot/structs.rs does not test struct destructuring
    • WEAK TESTS: Only int fields (BasicStruct) tested. Missing str/nested/generic destructure, match arm destructuring.
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.1) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.1 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.1: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.2 Sum Types (Enums) — COMPLETED 2026-01-28


  • Implement: Parse type Name = Variant1 | Variant2(Type)

    • Rust Tests: ori_parse/src/tests/parser.rs, ori_parse/src/tests/compositional.rs — sum type parsing tests
    • Ori Tests: tests/spec/declarations/sum_types.ori (30+ tests: unit, single-field, multi-field, generic, recursive, pattern matching)
    • AOT Tests: 30+ AOT tests across fat_matrix/f12_sum_payload.rs (8 tests), fat_matrix/f06_pattern_matching.rs (14 tests), fat_ptr_iter/struct_sum_tuple.rs (9 tests), derives.rs (sum type Eq tests)
  • Implement: Unit variants

    • Rust Tests: Covered in parser tests
    • Ori Tests: Color (Red|Green|Blue), Direction (NSEW), Toggle (On|Off), Status (4 variants)
  • Implement: Single-field variants Variant(Type)

    • Rust Tests: Covered in parser tests
    • Ori Tests: MyOption (MySome/MyNone), Message (Text/Empty)
    • AOT Tests: fat_matrix/f12_sum_payload.rs — sum payload codegen
  • Implement: Multi-field variants Variant(x: Type, y: Type)

    • Rust Tests: Covered in parser tests
    • Ori Tests: Shape (Circle/Rectangle), Point3D, Event (Click/KeyPress/Quit), Response (Success/Error)
    • AOT Tests: fat_matrix/f12_sum_payload.rs, fat_ptr_iter/struct_sum_tuple.rs — multi-field variant codegen
  • Implement: Struct variants

    • Rust Tests: Covered in parser tests — struct variant parsing (named fields)
    • Ori Tests: All multi-field variants use named fields
  • Implement: Variant constructors

    • Rust Tests: ori_types/src/infer/ — variant constructor type checking
    • Ori Tests: All sum type tests construct variants; generic sum types (MyResult, MyOptional, LinkedList, Tree)
    • AOT Tests: All sum type AOT tests exercise variant construction
  • Implement: Pattern matching on variants

    • Rust Tests: ori_types/src/infer/ — variant pattern matching
    • Ori Tests: Exhaustive match, wildcard, nested match, variable binding, recursive Expr eval
    • AOT Tests: fat_matrix/f06_pattern_matching.rs — 14 pattern matching AOT tests
    • Note: #derive(Eq) for sum types verified working — 16 tests in eq_sum.ori + EqColor/EqOption in sum_types.ori all pass
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.2) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.2 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.2: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.3 Newtypes

Proposal: proposals/approved/newtype-pattern-proposal.md


  • Implement: Parse type Name = ExistingType

    • Rust Tests: ori_parse/src/tests/parser.rs — newtype parsing tests
    • Ori Tests: tests/spec/types/newtypes.ori (UserId, Email, Age, Score — 9 tests)
    • WEAK TESTS: Only str and int underlying types tested. Missing bool, float, char, collections.
    • NEEDS PIN: No compile_fail test rejecting cross-newtype assignment (e.g., passing UserId where Email is expected).
  • Implement: Distinct type identity (nominal)

    • Rust Tests: ori_types/src/check/ (type registry) — nominal type identity
    • Ori Tests: tests/spec/types/newtypes.ori — separate UserId/Email types, validate_user/validate_email
    • LLVM Support: Transparent at runtime (same as underlying type)
  • Implement: Wrapping/unwrapping

    • Rust Tests: ori_eval/src/methods.rs — newtype unwrap method
    • Ori Tests: tests/spec/types/newtypes.ori — 9 tests (construction, unwrap, equality, params, computation)
    • LLVM Support: Transparent at runtime (newtype constructor just stores underlying value)
    • Note: Currently uses .unwrap() but spec mandates .inner — migration tracked in 5.3.4 below
  • Implement: Change .unwrap() to .inner accessor — spec/08-types.md § Newtypes (verified not implemented 2026-03-29)

    • Rust Tests: Update ori_eval/src/methods.rs tests to use .inner
    • Ori Tests: Update tests/spec/types/newtypes.ori to use .inner (all 9 tests use .unwrap())
    • LLVM Support: Update LLVM codegen to use .inner field access
    • AOT Tests: No AOT coverage yet
    • Note: .inner is always public regardless of newtype visibility
    • BUG FOUND: Tests use .unwrap() but spec/08-types.md section 8.6.3 mandates .inner. All 9 newtype tests will need migration when implemented.
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.3) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.3 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.3: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.4 Generic Types


  • Implement: Parse type Name<T> = ...

    • Rust Tests: ori_parse/src/tests/parser.rs — generic type parsing tests
    • Ori Tests: tests/spec/types/generic.ori (14 tests: Box, Pair<A,B>, Container, Wrapper — int/str/bool/list types, nested generics, method calls on fields)
  • Implement: Multiple parameters <T, U>

    • Rust Tests: Covered by parser tests
    • Ori Tests: tests/spec/types/generic.oritest_pair_int_str, test_pair_str_bool
  • Implement: Constrained <T: Trait> — spec/10-declarations.md § Generic Declarations

    • Rust Tests: ori_types/src/check/bound_checking.rs — constrained generics
    • Ori Tests: tests/spec/declarations/attributes.oriGenericDerived<T: Eq> works
    • LLVM Support: LLVM codegen for constrained generics
    • LLVM Rust Tests: ori_llvm/tests/generic_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • Implement: Multiple bounds <T: A + B> — spec/10-declarations.md § Generic Declarations

    • Rust Tests: ori_types/src/check/bound_checking.rs — multiple bounds
    • Ori Tests: Not tested yet
    • LLVM Support: LLVM codegen for multiple bounds
    • LLVM Rust Tests: ori_llvm/tests/generic_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • Implement: Generic application / Instantiation

    • Rust Tests: ori_types/src/infer/infer_struct handles instantiation
    • Ori Tests: tests/spec/types/generic.ori — 14 tests (Box, Box, Pair<int,str>, nested, chained access, method calls on fields)
    • Note: Type::Applied tracks instantiated generic types.
  • Implement: Constraint checking — spec/08-types.md § Generic Types

    • Rust Tests: ori_types/src/check/bound_checking.rs — constraint checking
    • Ori Tests: tests/spec/declarations/attributes.oriGenericDerived<T: Eq> constraint checked
    • LLVM Support: LLVM codegen for constraint checking
    • LLVM Rust Tests: ori_llvm/tests/generic_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.4) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.4 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.4: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.5 Compound Types

Note: tests/spec/types/collections.ori is ENTIRELY COMMENTED OUT (415 lines) — type checker doesn’t support collection type inference yet. Lists, tuples, maps work in the evaluator but type checker support is pending. HYGIENE: Commented-out code violates impl-hygiene.md (“No commented-out code ever: use version control”). File should have active tests or be empty with a tracking note.


  • Implement: List [T] — spec/08-types.md § List Type

    • Rust Tests: ori_types/src/infer/collections.rs — list type inference
    • Ori Tests: tests/spec/types/collections.ori — all commented out
    • LLVM Support: LLVM codegen for list type
    • LLVM Rust Tests: ori_llvm/tests/collection_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
    • Note: Lists work in evaluator (used in struct_types.ori, sum_types.ori) but type inference commented out
  • Implement: Map {K: V} — spec/08-types.md § Map Type

    • Rust Tests: ori_types/src/infer/collections.rs — map type inference
    • Ori Tests: tests/spec/types/collections.ori — all commented out
    • LLVM Support: LLVM codegen for map type
    • LLVM Rust Tests: ori_llvm/tests/collection_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • Implement: Set Set<T> — spec/08-types.md § Set Type

    • Rust Tests: ori_types/src/infer/collections.rs — set type inference
    • Ori Tests: tests/spec/types/collections.ori — all commented out
    • LLVM Support: LLVM codegen for set type
    • LLVM Rust Tests: ori_llvm/tests/collection_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • Implement: Tuple (T, U) — spec/08-types.md § Tuple Types [partial]

    • Parser: Numeric field access .0, .1expect_member_name() accepts integer literals (2026-02-15)
    • Parser Rust Tests: ori_parse/src/tests/parser.rstest_tuple_field_access, test_chained_tuple_field_access_with_parens, test_bare_chained_tuple_field_is_error (2026-02-15)
    • Ori Tests: tests/spec/types/tuple_types.ori — 30+ tests: unit, pair, triple, quad, mixed types, nested, collections, Option/Result, destructuring, params/returns, inference, equality, field access
    • Spec/Grammar: Updated grammar.ebnf § member_name, 09-expressions.md, 06-types.md (2026-02-15)
    • Rust Tests: ori_types/src/infer/ — tuple type inference
    • AOT Tests: ori_llvm/tests/aot/tuples.rs — 28 tests, 2 ignored (construction, field access, destructuring, nested tuples, function param/return, strings, control flow, closures, equality)
    • Parser: Chained field access without parens (t.0.1) — requires source text in parser or text in Float token
    • Note: Tuples work in evaluator and AOT. Comprehensive coverage across int/str/bool/float/char types, nested tuples, collections, Option/Result.
    • BUG FOUND: decision tree column count mismatch on tuple patterns with nested constructors + wildcard (e.g., (None, _)) — see compile/mod.rs:67
  • Implement: Range Range<T> — spec/08-types.md § Range Type

    • Rust Tests: ori_types/src/infer/ — range type inference
    • Ori Tests: tests/spec/expressions/loops.ori
    • LLVM Support: LLVM codegen for range type
    • LLVM Rust Tests: ori_llvm/tests/range_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • Implement: Function (T) -> U — spec/08-types.md § Function Types

    • Rust Tests: ori_types/src/infer/lambda.rs — function type inference
    • Ori Tests: tests/spec/expressions/lambdas.ori
    • LLVM Support: LLVM codegen for function types
    • LLVM Rust Tests: ori_llvm/tests/function_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
    • Note: Function types work in evaluator (used in struct_types.ori WithFunction)
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.5) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.5 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.5: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.6 Built-in Generic Types


  • Implement: Option<T> with Some/None

    • Rust Tests: ori_types/src/infer/ — Option type handling
    • Ori Tests: Used throughout test suite (struct_types.ori, sum_types.ori, traits/)
    • AOT Tests: AOT coverage exists in fat_ptr_iter/struct_sum_tuple.rs, fat_matrix/f12_sum_payload.rs
  • Implement: Result<T, E> with Ok/Err

    • Rust Tests: ori_types/src/infer/ — Result type handling
    • Ori Tests: Used in traits/core/ tests, tuple_types.ori, test suite
    • AOT Tests: AOT coverage exists in fat_ptr_iter tests
  • Implement: Ordering with Less/Equal/Greater

    • Rust Tests: ori_types/src/infer/ — Ordering type handling
    • Ori Tests: tests/spec/types/ordering/methods.ori (32+ tests), then_with.ori, match_ordering.ori
    • AOT Tests: No dedicated Ordering AOT tests yet
  • Implement: Error type — spec/17-errors-and-panics.md § Error Conventions

    • Rust Tests: ori_types/src/infer/ — Error type handling
    • Ori Tests: tests/spec/types/error.ori — not verified
    • LLVM Support: LLVM codegen for Error type
    • LLVM Rust Tests: ori_llvm/tests/error_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • Implement: Channel<T> — spec/08-types.md § Channel

    • Rust Tests: ori_types/src/infer/ — Channel type handling
    • Ori Tests: tests/spec/types/channel.ori — not implemented
    • LLVM Support: LLVM codegen for Channel type
    • LLVM Rust Tests: ori_llvm/tests/channel_tests.rs (file does not exist)
    • AOT Tests: No AOT coverage yet
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.6) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.6 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.6: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.7 with Clause on Type Declarations (Capability Unification)

Proposal: proposals/approved/capability-unification-generics-proposal.md — Phase 1

Replace #derive(Trait) with type T: Trait = .... Derivation moves from attribute syntax into the type declaration grammar as a : trait clause.

SUPERSEDES: Previous syntax #derive(Eq, Clone) and #[derive(Eq, Clone)] are both replaced by type T: Eq, Clone = { ... }.

Syntax Migration

  • Implement: Parser — parse : trait clause in parse_type_decl() between generics and where/=

    • Rust Tests: ori_parse/src/tests/parser.rs: trait clause parsing
    • Ori Tests: tests/spec/declarations/trait_clause.ori
  • Implement: IR — add derive_traits: Vec<DerivedTrait> to TypeDef node (replacing attribute-sourced data)

  • Implement: Remove parse_derive_attr() from parser; keep as migration error suggesting :

    • Ori Tests: tests/compile-fail/old_derive_syntax.ori
  • Migration: Update all #derive(...) in spec tests to : trait clause (~193 files)

  • Migration: Migration script (scripts/migrate_derive_syntax.py)

  • Update Spec: grammar.ebnftype_def production

  • Update: .claude/rules/ori-syntax.md — derive syntax

  • Verify: ./test-all.sh passes after migration

Existing Derive Functionality (carries forward)

All 7 derivable traits have AOT coverage in ori_llvm/tests/aot/derives.rs (43 tests passing, verified 2026-03-29).


  • Implement: Parse #[derive(Trait1, Trait2)] — to be replaced by : trait clause

    • Rust Tests: ori_parse/src/grammar/attr.rs — derive attribute parsing
    • Ori Tests: tests/spec/declarations/attributes.ori (15+ tests)
    • AOT Tests: ori_llvm/tests/aot/derives.rs — 43 tests covering all 7 derivable traits
  • Implement: #derive(Eq)

    • Rust Tests: ori_types/src/check/ (derive Eq) — derive Eq generation
    • Ori Tests: tests/spec/declarations/attributes.ori — EqPoint, EmptyDerived, SingleFieldDerived, nested derive, generic derive; tests/spec/traits/derive/eq.ori, eq_sum.ori (16 tests)
    • AOT Tests: ori_llvm/tests/aot/structs.rstest_struct_derived_eq, test_struct_derived_eq_string; ori_llvm/tests/aot/derives.rstest_aot_derive_eq_basic, test_aot_derive_eq_mixed_types, test_aot_derive_eq_single_field, test_aot_derive_eq_with_strings, test_aot_derive_eq_payload_sum_type, test_aot_derive_eq_mixed_variant_comparison, test_aot_derive_eq_single_payload_variant, test_aot_derive_multiple_traits, test_aot_journey_11_derived_eq (9+ tests, verified 2026-03-29)
    • Note: Derive(Eq) for sum types verified working — eq_sum.ori 16 tests + sum_types.ori EqColor/EqOption all pass
  • Implement: #derive(Clone)

    • Rust Tests: ori_types/src/check/ (derive Clone) — derive Clone generation
    • Ori Tests: tests/spec/declarations/attributes.ori — ClonePoint, SingleFieldDerived; tests/spec/traits/derive/clone.ori, all_derives.ori
    • AOT Tests: ori_llvm/tests/aot/derives.rstest_aot_derive_clone_basic, test_aot_derive_clone_large_struct + 12 primitive clone tests (int, float, bool, str, list_int, list_empty, option_some/none, result_ok/err, tuple_pair/triple) (14+ tests, verified 2026-03-29)
  • Implement: #derive(Hashable)

    • Rust Tests: ori_types/src/check/ (derive Hashable) — derive Hashable generation
    • Ori Tests: tests/spec/declarations/attributes.ori — HashPoint, MultiAttrPoint; tests/spec/traits/derive/hashable.ori; negative pin: tests/compile-fail/hashable_without_eq.ori
    • AOT Tests: ori_llvm/tests/aot/derives.rstest_aot_derive_hash_equal_values, test_aot_derive_hash_different_values, test_aot_derive_hash_float_neg_zero, test_aot_derive_hash_str_content, test_aot_derive_hash_byte_field (5 tests, verified 2026-03-29)
  • Implement: #derive(Debug) — spec/10-declarations.md § Attributes

    • Rust Tests: ori_types/src/check/derives/ — derive Debug generation
    • Ori Tests: tests/spec/traits/derive/debug.ori, tests/spec/declarations/attributes.ori — DebugPoint
    • AOT Tests: ori_llvm/tests/aot/derives.rstest_aot_derive_debug_short_str_no_leak, test_aot_derive_debug_str_field_no_leak, test_aot_derive_debug_mixed_str_int_no_leak, test_aot_derive_debug_multi_str_no_leak (4 tests, verified 2026-03-29)
    • Note: attributes.ori DebugPoint test only checks debug_str.len() > 0 — WEAK assertion, does not verify format. Dedicated debug.ori and AOT tests are stronger.
  • Implement: #derive(Printable) — spec/10-declarations.md § Attributes

    • Rust Tests: ori_types/src/check/derives/printable.rs — derive Printable generation
    • Ori Tests: tests/spec/traits/derive/printable.ori — struct basic, single str field, nested struct, payloadless variants, sum type variants with payloads (all pass)
    • AOT Tests: ori_llvm/tests/aot/derives.rstest_aot_derive_printable_basic (1 test, verified 2026-03-29)
  • Implement: #derive(Default) — spec/10-declarations.md § Attributes

    • Rust Tests: ori_types/src/check/derives/default.rs — derive Default generation
    • Ori Tests: tests/spec/traits/derive/default.ori — Point (int->0), Config (str->"", int->0, bool->false), single field, float fields (all pass). Negative: tests/compile-fail/default_sum_type.ori rejects derive(Default) on sum types.
    • AOT Tests: ori_llvm/tests/aot/derives.rstest_aot_derive_default_basic, test_aot_derive_default_str_field, test_aot_derive_default_mixed_types, test_aot_derive_default_nested, test_aot_derive_default_eq_integration (5 tests, verified 2026-03-29)
  • Implement: #derive(Comparable) — spec/08-types.md § 8.6.4

    • Rust Tests: ori_ir/derives/mod.rs — DerivedTrait::Comparable variant
    • Ori Tests: tests/spec/traits/derive/comparable.ori (struct comparison), tests/spec/traits/derive/comparable_sum.ori (sum type variant ordering)
    • AOT Tests: ori_llvm/tests/aot/derives.rstest_aot_derive_comparable_basic, test_aot_derive_comparable_single_field, test_aot_derive_comparable_with_strings, test_aot_derive_comparable_first_field_wins (4 tests, verified 2026-03-29)
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.7) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.7 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.7: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.8 Visibility


  • Implement: Parse pub type Name = ...

    • Rust Tests: ori_parse/src/grammar/item.rs — pub type parsing
    • Ori Tests: tests/spec/declarations/struct_types.oripub type PublicStruct, tests/spec/declarations/sum_types.oripub type PublicStatus
    • AOT Tests: No AOT coverage yet
  • Implement: Public visible from other modules

    • Rust Tests: ori_eval/src/interpreter/module/visibility.rs — public visibility
    • Ori Tests: tests/spec/modules/use_imports.oripub type Point imported cross-module
    • AOT Tests: No AOT coverage yet
    • WEAK TESTS: No cross-module import test importing from a separate file and verifying pub types are accessible.
  • Implement: Private only in declaring module

    • Rust Tests: ori_eval/src/interpreter/module/visibility.rs — private visibility
    • Ori Tests: tests/spec/modules/use_imports.oritype InternalPoint (private)
    • AOT Tests: No AOT coverage yet
    • NEEDS PIN: No compile_fail test for private type import rejection from another module.
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.8) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.8 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.8: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.9 Associated Functions

Proposal: proposals/approved/associated-functions-language-feature.md

Generalize associated functions to work for ANY type with an impl block, removing hardcoded type checks. Enables syntax like Point.origin(), Builder.new(), Duration.from_seconds(s: 10).

Migration

  • Implement: Remove is_type_name_for_associated_functions() hardcoded checks

    • Rust Tests: ori_types/src/infer/ (calls) — general type name resolution
    • Ori Tests: tests/spec/types/associated_functions.ori — user types (Point, Builder, Counter, Rectangle, Pair) all work (12+ tests)

Parsing

  • Implement: Parse Type.method(...) syntax in expression position

    • Rust Tests: ori_parse/src/grammar/postfix.rs — type-prefixed method call
    • Ori Tests: Point.origin(), Builder.new(), Counter.zero(), Rectangle.square(size: 5)
  • Implement: Distinguish type name vs value in resolution

    • Rust Tests: ori_types/src/infer/ — type vs value resolution
    • Ori Tests: test_instance_vs_associatedPair.create() (type) vs p.sum() (value)

Associated Function Registry

  • Implement: Track methods without self in impl blocks

    • Rust Tests: ori_types/src/check/ (method registry) — associated function registry
    • Ori Tests: Point.origin(), Point.new(), Builder.new(), Counter.zero(), Counter.starting_at(), Rectangle.square/from_dimensions/unit(), Pair.create()
  • Implement: Built-in associated functions for Duration

    • Ori Tests: tests/spec/types/associated_functions.oriDuration.from_seconds(s: 5) verified
    • Duration.from_nanoseconds(ns:), from_microseconds(us:), from_milliseconds(ms:)
    • Duration.from_seconds(s:), from_minutes(m:), from_hours(h:)
  • Implement: Built-in associated functions for Size

    • Ori Tests: tests/spec/types/associated_functions.oriSize.from_megabytes(mb: 2) verified
    • Size.from_bytes(b:), from_kilobytes(kb:), from_megabytes(mb:)
    • Size.from_gigabytes(gb:), from_terabytes(tb:)

Generic Types

  • Implement: Full type arguments required for generic associated functions

    • Ori Tests: Not tested — Option<int>.some(value: 42) pattern not verified
    • Example: Option<int>.some(value: 42)

Self Return Type

  • Implement: Allow Self as return type in associated functions

    • Ori Tests: tests/spec/types/associated_functions.ori — Point.origin() -> Self, Builder.new() -> Self, Counter.zero() -> Self, Counter.increment(self) -> Self

Trait Associated Functions

  • Implement: Traits can define associated functions without self

    • Rust Tests: ori_types/src/check/registration/traits.rs — trait associated functions
    • Ori Tests: Not tested — trait Default { @default () -> Self } pattern
    • Example: trait Default { @default () -> Self }

LLVM Support


  • LLVM Support: Codegen for associated function calls [partial]

    • AOT Tests: Partial — ori_llvm/tests/aot/traits.rs has test_aot_inherent_impl_method, test_aot_impl_method_field_access (inherent impl methods work in AOT, verified 2026-03-29)
    • AOT Tests: No dedicated associated function (no self) AOT tests yet
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)

  • /impl-hygiene-review passed — hygiene review clean. MUST run AFTER /tpr-review is clean.

  • Subsection close-out (5.9) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.9 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.9: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.

  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.

  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.

5.10 Section Completion Checklist

Exit Criteria: User-defined structs and enums work Status: Evaluator and AOT support complete for core features. All 7 derivable traits verified with eval + AOT coverage (43 AOT derive tests in derives.rs). Type checker compound inference, capability unification syntax, and newtype .inner accessor pending. Verified 2026-03-29.

  • Struct types (definition, literal, shorthand, field access, destructuring, spread, generic)
  • Sum types (unit, single-field, multi-field, generic, recursive, pattern matching)
  • Newtypes (construction, unwrap, nominal identity)
  • Generic types (single/multiple params, instantiation, field access chain)
  • Built-in generics: Option, Result, Ordering
  • Derive: Eq, Clone, Hashable on structs
  • Derive: Debug, Printable, Default — working
  • Derive: Comparable — working
  • Derive(Eq) for sum types — working
  • Visibility: pub type, private by default
  • Associated functions: Type.method() for user types, Duration, Size
  • AOT coverage: structs (30 tests), sum types (30+ tests), tuples (28 tests), all 7 derives (43 tests), Option, Result
  • Compound type inference (5.5) — entirely pending (collections.ori all commented out)
  • Newtype .inner accessor migration — pending (spec/08-types.md mandates .inner, tests use .unwrap())
  • Generic associated functions with type args — not tested
  • Trait associated functions — not tested
  • Capability unification syntax migration (: trait clause) — not started
  • Struct destructuring AOT tests — missing
  • Struct shorthand AOT tests — missing
  • Newtype negative pin tests (cross-newtype assignment) — missing
  • Visibility negative pin tests (private type import rejection) — missing
  • Commented-out collections.ori cleanup — hygiene violation
  • Run full test suite: ./test-all.sh
  • /tpr-review passed — independent Codex review found no critical or major issues (or all findings triaged)
  • /impl-hygiene-review passed — implementation hygiene review clean (phase boundaries, SSOT, algorithmic DRY, naming). MUST run AFTER /tpr-review is clean.
  • /improve-tooling retrospective completed — MANDATORY at section close, after both reviews are clean. Reflect on the section’s debugging journey (which diagnostics/ scripts you ran, which command sequences you repeated, where you added ad-hoc dbg!/tracing calls, where output was hard to interpret) and identify any tool/log/diagnostic improvement that would have made this section materially easier OR that would help the next section touching this area. Implement every accepted improvement NOW (zero deferral) and commit each via SEPARATE /commit-push. The retrospective is mandatory even when nothing felt painful — that is exactly when blind spots accumulate. See .claude/skills/improve-tooling/SKILL.md “Retrospective Mode” for the full protocol.
  • /tpr-review passed — independent review found no critical or major issues (or all findings triaged)
  • Subsection close-out (5.10) — MANDATORY before starting the next subsection. Run /improve-tooling retrospectively on THIS subsection’s debugging journey (per .claude/skills/improve-tooling/SKILL.md “Per-Subsection Workflow”): which diagnostics/ scripts you ran, where you added dbg!/tracing calls, where output was hard to interpret, where test failures gave unhelpful messages, where you ran the same command sequence repeatedly. Forward-look: what tool/log/diagnostic would shorten the next regression in this code path by 10 minutes? Implement improvements NOW (zero deferral) and commit each via SEPARATE /commit-push using a valid conventional-commit type (build(diagnostics): ... — surfaced by section-5.10 retrospectivebuild/test/chore/ci/docs are valid; tools(...) is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 5.10: no tooling gaps”. Update this subsection’s status in section frontmatter to complete.
  • /sync-claude section-close doc sync — verify Claude artifacts across all section commits. Map changed crates to rules files, check CLAUDE.md, canon.md. Fix drift NOW.
  • Repo hygiene check — run diagnostics/repo-hygiene.sh --check and clean any detected temp files.