Section 21A: LLVM Backend
Current Test Results (verified 2026-04-06)
| Test Suite | Passed | Failed | Skipped/Ignored | Total |
|---|---|---|---|---|
| Ori spec (evaluator) | 4409+ | 0 | 154 | 4563+ |
| Rust unit tests (ori_llvm lib) | 501+ | 0 | 0 | 501+ |
| AOT integration tests | 2096+ | 0 | 0 | 2096+ |
| ori_rt unit tests | 367+ | 0 | 0 | 367+ |
| Ori spec (LLVM) | 1781+ | 0 | 2475 LCFail | 4256+ |
Known Blocker: BUG-04-030 — 2475 LCFails (high severity)
See plans/bug-tracker/section-04-codegen-llvm.md:198 for full details.
Root causes (6 identified, 3 remaining after JIT EH plan fixes):
- (A) Generalized vars leak to codegen — type checker stores unresolved vars in expr_types. ~279 occurrences. Touches §21.2 (Type Lowering) and §21.7 (Monomorphization).
- (B) Index out of bounds (u32::MAX) in ARC IR — missing block/var ID sentinel. ~50+ files. Touches §21.15 (ARC/Memory Management).
- (C) StructValue vs IntValue type confusion — 4 files. Touches §21.2 (Type Lowering).
(D) Missing JIT runtime functions— fixed in JIT EH plan §06.1.(E) Polymorphic type selection— fixed in JIT EH plan §06.4.(F) List concat calling convention— fixed in JIT EH plan §06.5.
Resolving remaining root causes (A, B, C) would unblock completion of the JIT Exception Handling plan (Sections 04B, 05, 06).
Import Resolution (Unified Pipeline)
Correction callout (2026-04-20): The Import Resolution behavior documented below, plus subsection 21.7 (generic monomorphization) and 21.11 (lambda / closure support), was CORRECTED by
plans/empty-container-typeck-phase-contract/section-08-codegen-poly-lambda.md(resolves BUG-04-042). The “verified 2026-03-29” monomorphization claim below was contradicted by a commit-wall regression whereassert_eq<T>failed to monomorphize in poly-lambda hosts — root cause was cross-module pool-mergevar_idcollision in the JIT test runner’s pool merge (fix landed in §08.3pool/re_intern/) plus scheme-bodyGeneralized→BoundVarcanonicalization (§08.3b / §08.3b.1) plus newtype constructor lowering (§08.3c). Any future §21A resumption MUST consult §08 before modifying generic monomorphization or lambda_mono / poly-lambda paths incompiler/ori_llvm/src/codegen/function_compiler/and the test-runner pool-merge path incompiler/oric/src/test/runner/llvm_backend.rs.
The JIT test runner resolves imports via oric::imports::resolve_imports() and compiles
imported function bodies directly into the JIT module. This uses the same declare_all /
define_all path as main module functions, so most new codegen features automatically
work for imported functions too.
Features that need import-aware changes
When implementing these features, ensure they also work across module boundaries:
-
Generic monomorphization: IMPLEMENTED (verified 2026-03-29; corrected 2026-04-20 by §08.3/§08.3b/§08.3b.1 — see correction callout above). 33 generics tests pass including cross-module
assert_eqinstantiation. -
Impl blocks from imported modules: IMPLEMENTED (verified 2026-03-29). Imported modules’ impl blocks are compiled via
compile_impls(). -
Type declarations from imported modules: IMPLEMENTED (verified 2026-03-29).
register_user_types()processes imported modules’ type declarations. -
Prelude functions: IMPLEMENTED (verified 2026-03-29). Sum type codegen works; prelude compilation re-enabled.
21.1 LLVM Setup & Infrastructure (verified 2026-03-29)
-
Setup: LLVM development environment
- Docker container with LLVM 21 and development headers
- Add
inkwellcrate tocompiler/ori_llvm/Cargo.toml - Verify LLVM bindings compile and link correctly
- Create
compiler/ori_llvm/src/module structure
-
Implement: LLVM context and module initialization
- Rust Tests:
context.rs— SimpleCx, CodegenCx, TypeCache - Create LLVM context, module, and builder abstractions
- Rust Tests:
-
Implement: Basic target configuration
- Support native target detection (JIT)
- Configure data layout and target features (AOT)
21.2 Type Lowering (verified 2026-03-29)
-
Implement: Primitive type mapping
- Rust Tests:
types.rs,context.rs— type mapping - Map Ori primitives (int → i64, float → f64, bool → i1, char → i32, byte → i8)
- Map strings to
{ i64 len, ptr data }struct - Handle function types
- Rust Tests:
-
Implement: Option/Result types
- Map Option/Result to
{ i8 tag, i64 payload }tagged unions - Tag values: None=0, Some=1; Err=0, Ok=1
- Proper payload handling for non-primitive types
- Map Option/Result to
-
Implement: Collection type representations in
ori_llvm/src/codegen/— list/map/set LLVM struct layouts- Map lists to
{ i64 len, i64 cap, ptr data }struct - Map maps to appropriate hash table representation
- Map sets to appropriate hash set representation
- Map lists to
-
Implement: Duration & Size types
- Map Duration to i64 (nanoseconds)
- Map Size to i64 (bytes)
- Duration arithmetic operations (add, sub, mul, div, mod)
- Size arithmetic operations (add, sub, mul, div, mod)
- Size cross-unit normalization —
512kb + 512kb == 1mbequality fails in AOT (test_op_size_arithmetic) - Mixed-type arithmetic (Duration * int, int * Duration, Duration / Duration → int)
- Size unary negation compile error
- Overflow panic semantics for Duration
- Division by zero panics
- Duration methods:
.nanoseconds(),.microseconds(),.milliseconds(),.seconds(),.minutes(),.hours() - Size methods:
.bytes(),.kilobytes(),.megabytes(),.gigabytes(),.terabytes() - Factory functions:
Duration.from_nanoseconds(ns:),Size.from_bytes(b:)
-
Implement: Newtype codegen in
ori_llvm/src/codegen/— transparent wrapper representation- Newtype type representation (same as wrapped type)
- Constructor codegen:
TypeName(value) -
.innerfield access - Proper type distinction for trait dispatch
-
Implement: Sum type codegen (beyond Option/Result)
- User-defined sum type representation (tagged union)
- Variant constructor codegen
- Tag-based dispatch in match
- Multi-field variant payloads
- Import note: Once sum types work, re-enable prelude function compilation in
JIT mode (
runner.rs). Currently skipped becausecompare() -> Orderingfails.
-
Implement: Fixed-capacity lists
[T, max N]- Inline allocation strategy
- Compile-time capacity tracking
-
.capacity(),.is_full(),.remaining()methods -
.push()with panic on full -
.try_push()→bool -
.push_or_drop(),.push_or_oldest() -
.to_dynamic()conversion -
.to_fixed<$N>()and.try_to_fixed<$N>()
-
Implement: Channel type codegen —
Producer<T>/Consumer<T>LLVM representations and runtime calls-
Producer<T>andConsumer<T>type representation -
CloneableProducer<T>andCloneableConsumer<T> -
Sendabletrait constraint checking - Channel buffer management
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.2) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.2 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.2: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.3 Expression Codegen (verified 2026-03-29)
-
Implement: Core expression codegen — literals, binary/unary ops, calls, field access in
ori_llvm/src/codegen/- Rust Tests:
tests/arithmetic_tests.rs,tests/operator_tests.rs - Literals (int, float, bool, string, char, byte)
- Binary ops (add, sub, mul, div, mod, comparisons, logical)
- Unary ops (neg, not)
- Function calls and method dispatch
- Field access and basic indexing
- Rust Tests:
-
Implement: Range expressions with step
-
start..end by stepcodegen -
start..=end by stepinclusive ranges - Negative step support (descending:
10..0 by -1) - Infinite ranges:
0..,0.. by step - Zero-step panic
- Empty range detection (mismatched direction)
-
-
Implement: Spread operator
...- List spread:
[...a, x, ...b] - Map spread:
{...a, key: v, ...b} - Struct spread:
Point { ...orig, x: 10 } - Later-wins merge semantics
- List spread:
-
Implement: Coalesce operator
??-
option ?? defaultcodegen -
result ?? defaultcodegen - Short-circuit evaluation
- Type inference for coalesce chains
-
-
Implement: Floor division operator
div- Integer floor division codegen
- Distinct from
/(truncating division)
-
Implement: Bitwise operator codegen —
~/&/|/^/<</>>for int and byte types-
~(BitNot) codegen -
&,|,^for int and byte types -
<<,>>shift operators - Shift overflow panics (count < 0 or count >= bit width)
-
-
Implement: Type conversion codegen —
as/as?/Intotrait dispatch in LLVM IR-
expr as Typeinfallible conversion codegen -
expr as? Typefallible conversion →Option<T> - Standard conversions: int→float, str→Error, Set
→[T] - Into trait method dispatch
-
-
Implement: Assignment to complex targets
- Field assignment:
point.x = 10 - Index assignment:
list[0] = value - Nested assignments:
a.b.c = value
- Field assignment:
-
Implement: String operation codegen — indexing, interpolation, escapes, methods via
ori_rtcalls (verified 2026-03-29)- String indexing with Unicode handling (
str[i]→ single-codepointstr) - String interpolation:
`Hello {name}` - All escape sequences:
\n,\t,\r,\0,\\,\" -
str.concat()return type tracking — FIXED (test_str_concat_basicpasses) -
str.to_str()identity return type tracking — FIXED (test_str_to_str_identitypasses) - String ordering (
<,>,<=,>=) — FIXED (test_str_compare_lesspasses) - String methods in builtin table:
contains,starts_with,ends_with,trim,to_uppercase,to_lowercase,replace,split,repeat,chars— FIXED (tests pass) - Struct update (
...spread) with string fields — FIXED (test_struct_update_with_stringpasses)
- String indexing with Unicode handling (
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.3) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.3 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.3: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.4 Operator Trait Dispatch (verified 2026-03-29)
-
Implement: User-defined impl blocks and associated functions
- Register user-defined struct types with LLVM
- Support user-defined
impl Type { ... }blocks - Generate method dispatch for user-defined methods
- Support associated functions (methods without
selfparameter) - Enable
Type.method()syntax for user-defined types - Import note: Compile imported modules’ impl blocks via
compile_impls() - Import note:
register_user_types()processes imported modules’ type declarations - Tests:
tests/spec/types/associated_functions.ori(9 tests passing)
-
Implement: User-defined operator dispatch
- Rust Tests:
tests/operator_trait_tests.rs - Detect when operand is a user-defined type (struct)
- Generate method calls to trait methods instead of direct LLVM ops
- Arithmetic operators →
.add(),.subtract(),.multiply(),.divide(),.floor_divide(),.remainder() - Unary operators →
.negate(),.not(),.bit_not() - Bitwise operators →
.bit_and(),.bit_or(),.bit_xor(),.shift_left(),.shift_right() - Comparison operators →
.equals(),.compare() - Tuple
==equality — FIXED (test_tuple_equality,test_tuple_equality_triplepass) - Handle generic operator traits with type parameters (e.g.,
Mul<int>) - Files:
ori_llvm/src/operators.rs— trait dispatch logic - Tests:
tests/spec/traits/operators/user_defined.ori(currently skipped)
- Rust Tests:
-
Implement: Overflow and panic semantics
- Integer overflow detection and panic
- Division by zero panic for integers
- Shift count validation (negative or >= bit width → panic)
- Float special cases: Inf, NaN handling
- NaN comparison semantics (NaN > all values)
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.4) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.4 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.4: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.5 Control Flow (verified 2026-03-29)
-
Implement: Basic control flow
- Rust Tests:
tests/control_flow_tests.rs,tests/advanced_control_flow_tests.rs - Basic block creation and linking
- Phi nodes for SSA form
- Branch and conditional instructions
- Basic break/continue in loops
- Rust Tests:
-
Implement: Labeled loops
-
loop:namesyntax support -
for:namesyntax support -
break:nametargeting specific loop -
continue:nametargeting specific loop -
continue:name valuein yield context - No label shadowing enforcement
-
-
Implement: Break with values
-
break valuecodegen - Phi node setup in loop exit block
- Type resolution for loop expressions with break values
-
break:name valuefor labeled loops
-
-
Implement: For-yield expressions
-
for x in items yield expr→ list collection -
for x in items if guard yield exprwith filtering - Nested for-yield:
for x in xs for y in ys yield (x, y) -
continue valuesubstitution in yield -
break valuefinal element addition -
{K: V}collection from(K, V)tuples - Bool comparison stored in struct field during for-yield — FIXED (
test_depth_combined_struct_iter_matchpasses) - Mutation of outer variables inside match arms within for-do body — FIXED (
test_depth_combined_match_closure_resultpasses)
-
-
Implement: Try expression and error propagation
-
?operator on Result: unwrap or early return -
?operator on Option: unwrap or early return None - Proper error propagation up call stack
- Result accumulation in try blocks
-
-
Implement: Catch pattern
-
catch(expr:)→Result<T, str>codegen - Panic recovery mechanism
- Error message capturing
- BUG:
catch()type inference returnsResult<() -> T, str>instead ofResult<T, str>— blocks 12 AOT tests (type checker bug, not LLVM) - BUG: Inline panic in
catch—invokeonly intercepts callee-function panics, not same-function inline code (e.g.,1 / 0) — blocks 1 AOT test
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.5) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.5 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.5: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.6 Pattern Matching (verified 2026-03-29)
-
Implement: Basic patterns
- Literal patterns
- Binding patterns
- Wildcard patterns
_ - Basic struct destructuring
- Basic tuple destructuring
-
Implement: Advanced patterns
- Range patterns:
1..10,'a'..'z' - Or-patterns:
A | B | C - At-patterns:
x @ Some(_) - Guard patterns:
x if x > 0 - Struct destructuring with field renaming:
{ x: px, y: py } - List patterns with rest:
[first, ..rest],[..init, last] - Nested patterns
- Range patterns:
-
Implement: Match expression improvements
- Exhaustiveness verification in codegen
- Never variant handling
- Pattern matrix optimization
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.6) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.6 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.6: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.7 Function Sequences & Expressions (verified 2026-03-29; corrected 2026-04-20 per §08)
-
Implement: Generic function monomorphization (verified 2026-03-29 — 33 generics tests pass)
- Collect monomorphization sites (call sites with concrete type args)
- Clone generic function bodies with type substitution
- Re-type-check monomorphized bodies to get concrete expr_types
- Compile specialized instances through normal declare/define path
- Import: collect call sites from calling module and generate specialized versions of imported generic functions (e.g.,
assert_eq<int>) - Implementation plan: Monomorphization (4 sections: type checker, ARC lowering, LLVM pipeline, verification)
- Architecture document:
docs/ori_lang/v2026/design/monomorphization-architecture.md
-
Implement: Basic function codegen
- Rust Tests:
tests/function_tests.rs,tests/function_call_tests.rs - Function signatures and calling conventions
- Local variables
- Return statements
- Rust Tests:
-
Implement: Block expressions and control flow (
{ },try,match)-
{ let x = a \n result }sequential binding via block expressions -
pre(cond) post(r -> cond)function-level contract declarations -
try { let x = f()? \n Ok(x) }error propagation -
match v { P -> e, _ -> d }pattern matching
-
-
Fix: Block scope variable isolation (verified 2026-03-29)
- Inner block
let xleaks to outer scope — FIXED (test_scope_shadow_in_nested_blockpasses) -
let xin for-do body overwrites outerx(test_scope_for_loop_shadow) — no test exists to verify
- Inner block
-
Implement: Recurse pattern
-
recurse(condition:, base:, step:)basic recursion -
memo:memoization support -
parallel:parallel recursion flag - Proper state threading
-
-
Implement: With pattern (RAII)
-
with(acquire:, use:, release:)codegen - Guaranteed release even on panic
- Resource binding in
use:block - Note: Evaluator has a loud stub in
can_eval.rs— replace stub with real impl when ready
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.7) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.7 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.7: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.8 Concurrency Patterns
Related Proposals:
-
proposals/approved/parallel-execution-guarantees-proposal.md -
proposals/approved/timeout-spawn-patterns-proposal.md -
proposals/approved/nursery-cancellation-proposal.md -
proposals/approved/sendable-channels-proposal.md -
proposals/approved/cache-pattern-proposal.md -
proposals/approved/task-async-context-proposal.md -
Implement: Parallel pattern
-
parallel(tasks:, max_concurrent:, timeout:)→[Result] - Task spawning using OS threads or async runtime
- Result collection preserving task order
- Timeout handling with cancellation propagation
-
uses Suspendcapability requirement -
Sendablebound on task return types - Rust Tests:
ori_llvm/src/concurrency/parallel_tests.rs - Evaluator: Replace loud stub in
can_eval.rs:eval_can_function_expwith real parallel eval
-
-
Implement: Spawn pattern
-
spawn(tasks:, max_concurrent:)→void - Fire-and-forget semantics (errors logged, not propagated)
- Background execution with structured lifetime
- Tasks must complete before parent scope exits
- Rust Tests:
ori_llvm/src/concurrency/spawn_tests.rs - Evaluator: Replace loud stub in
can_eval.rs:eval_can_function_expwith real spawn eval
-
-
Implement: Timeout pattern
-
timeout(op:, after:)→Result<T, TimeoutError> - Operation cancellation on timeout via
is_cancelled()checks - Cleanup: resources released, destructors run
- Cooperative cancellation model (no preemption)
- Rust Tests:
ori_llvm/src/concurrency/timeout_tests.rs - Evaluator: Replace loud stub in
can_eval.rs:eval_can_function_expwith real timeout eval
-
-
Implement: Cache pattern
-
cache(key:, op:, ttl:)codegen - Cache key hashing via
Hashabletrait - TTL management with Duration type
- Thread-safe cache access
-
uses Cachecapability requirement - Rust Tests:
ori_llvm/src/concurrency/cache_tests.rs - Evaluator: Replace loud stub in
can_eval.rs:eval_can_function_expwith real cache eval
-
-
Implement: Nursery pattern
-
nursery(body:, on_error:, timeout:)codegen -
NurseryErrorMode.CancelRemaining: cancel siblings on first failure -
NurseryErrorMode.CollectAll: run all, collect all errors -
NurseryErrorMode.FailFast: return first error immediately - Structured concurrency: all children complete before nursery returns
- Cancellation propagation via
CancellationError - Rust Tests:
ori_llvm/src/concurrency/nursery_tests.rs
-
-
Implement: Channel operations
-
channel<T>(buffer:)→(Producer, Consumer)creation -
T: Sendablebound enforced at compile time -
channel_in,channel_out,channel_allselection patterns - Blocking send/receive operations
- Bounded buffer with backpressure
-
CloneableProducer<T>,CloneableConsumer<T>variants - Rust Tests:
ori_llvm/src/concurrency/channel_tests.rs
-
-
Implement: Sendable trait enforcement
- Check
Sendablebound for all cross-task data - Compile error for non-Sendable types in parallel contexts
- Interior mutability rules per
sendable-interior-mutability-proposal.md
- Check
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.8) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.8 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.8: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.9 Capabilities & With Pattern
Related Proposals:
-
proposals/approved/capability-composition-proposal.md -
proposals/approved/with-pattern-proposal.md -
proposals/approved/default-impl-proposal.md -
proposals/approved/default-impl-resolution-proposal.md -
proposals/approved/intrinsics-capability-proposal.md -
Implement: Capability tracking
-
uses Capabilitydeclaration in function signatures - Capability propagation through call graph
- Compile error if capability not available at call site
- Transitive capability requirements
- Rust Tests:
ori_llvm/src/capabilities/tracking_tests.rs
-
-
Implement: Capability provision
-
with Cap = impl in exprcodegen - Multiple capabilities:
with A = a, B = b in expr - Provider vtable generation
- Implicit capability parameter threading
- Scope-based resolution (innermost
withwins) - Rust Tests:
ori_llvm/src/capabilities/provision_tests.rs
-
-
Implement: Default implementations
-
def implvtable generation at module level - Resolution order: with scope > imported def impl > local def impl
- Override with explicit
withpattern -
without defimport to exclude default impl - One def impl per trait per module
- Rust Tests:
ori_llvm/src/capabilities/default_impl_tests.rs
-
-
Implement: Standard capabilities
-
Print(default provided, writes to stdout) -
Http(network requests) -
FileSystem(file I/O) -
Clock(time queries) -
Random(random number generation) -
Crypto(cryptographic operations) -
Cache(memoization and caching) -
Logger(structured logging) -
Env(environment variables) -
Intrinsics(SIMD, bit ops per intrinsics-capability-proposal) -
Suspend(async/concurrency marker) -
FFI(foreign function interface) - Rust Tests:
ori_llvm/src/capabilities/standard_tests.rs
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.9) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.9 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.9: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.10 Collections & Iterators
Related Proposals:
-
proposals/approved/iterator-traits-proposal.md -
proposals/approved/iterator-performance-semantics-proposal.md -
proposals/approved/computed-map-keys-proposal.md -
proposals/approved/fixed-capacity-list-proposal.md -
Implement: List operations (verified 2026-03-29 — 82 collections_ext tests pass)
-
.push(element:)- append to end, grow if needed (test_coll_list_push) -
.pop()→Option<T>- remove and return last element (test_coll_list_pop) -
.first()→Option<T>- return first element (test_coll_list_first) -
.last()→Option<T>- return last element (test_coll_list_last) -
.insert(at:, element:)- insert at index, shift elements -
.remove(at:)→T- remove at index, shift elements -
.get(index:)→Option<T>- safe indexed access -
list[index]→T- direct access (panics if out of bounds) (test_coll_list_index) -
list[# - 1]- length-relative indexing -
.reverse()- return reversed list (test_coll_list_reverse) -
.contains(element:)→bool(test_coll_list_contains) -
.concat(other:)— FIXED (test_aot_list_concatpasses) - Capacity management: grow by 2x when full
- List iteration:
for x in list do ... - List-of-tuples iteration — FIXED (
test_tuple_in_looppasses) - Rust Tests:
ori_llvm/src/collections/list_tests.rs
-
-
Implement: Map operations (verified 2026-03-29 — collections_ext tests pass)
- Map literal:
{key: value},{"string": value} - Computed keys:
{[expr]: value}where expr is evaluated -
.get(key:)→Option<V>- lookup by key (test_coll_map_get) -
map[key]→Option<V>- subscript access -
.insert(key:, value:)- insert or update (test_coll_map_insert) -
.remove(key:)→Option<V>- remove and return (test_coll_map_remove) -
.is_empty()→bool(test_aot_map_is_empty) -
.contains_key(key:)→bool(test_coll_map_contains_key) -
.keys()→[K]- return list of keys (test_coll_map_keys) -
.values()→[V]- return list of values (test_coll_map_values) - Map iteration: yields
(K, V)tuples - Spread in literals:
{...base, key: value} - Rust Tests:
ori_llvm/src/collections/map_tests.rs
- Map literal:
-
Implement: Set operations [partial]
-
Set<T>type representation:{i64 len, i64 cap, ptr data}(same as list — sorted flat array, not hash set) - Set creation in AOT:
__collect_setimplemented — intercepts inemit_apply, callsori_iter_collect_setruntime (2026-03-01) -
.len()→emit_set_length()— extract field 0 -
.is_empty()→emit_set_is_empty()—len == 0 -
.contains(element:)→emit_set_contains()viaori_set_containsruntime -
.insert(element:)→emit_set_insert()viaori_set_insertruntime (returns new set via sret) -
.remove(element:)→emit_set_remove()viaori_set_removeruntime (returns new set via sret) -
.union(other:)→emit_set_union()viaori_set_unionruntime (sret) -
.intersection(other:)→emit_set_intersection()viaori_set_intersectionruntime (sret) -
.difference(other:)→emit_set_difference()viaori_set_differenceruntime (sret) -
.to_list()→emit_set_to_list()viaori_set_to_listruntime (sret) - Set iteration: yields
Telements (set.iter()codegen) - Runtime functions: 7 functions in
ori_rt/src/lib.rs+ declarations inruntime_decl/mod.rs - AOT Tests:
ori_llvm/tests/aot/sets.rs— 10 tests all passing (2026-03-01)
-
-
Implement: Iterator trait codegen (partial — 25 iterator tests pass, verified 2026-03-29)
-
Iteratortrait:type Item; @next (self) -> (Option<Self.Item>, Self) -
DoubleEndedIteratortrait:@next_back (self) -> (Option<Self.Item>, Self) - Fused iterator semantics:
NonestaysNone -
.map(transform:)- lazy transformation -
.filter(predicate:)- lazy filtering -
.fold(initial:, op:)- eager reduction -
.collect()into target collection viaCollecttrait -
.enumerate()- yield(index, item)tuples -
.zip(other:)- pair with another iterator -
.chain(other:)- concatenate iterators -
.take(count:),.skip(count:)- limit iteration -
.cycle()- repeat infinitely - Copy elision: avoid intermediate allocations
- Rust Tests:
ori_llvm/src/collections/iterator_tests.rs
-
-
Implement: DoubleEndedIterator methods
-
.rev()- reverse iteration order -
.last()- get last element -
.rfind(predicate:)- find from end -
.rfold(initial:, op:)- fold from end - Rust Tests:
ori_llvm/src/collections/double_ended_tests.rs
-
-
Implement: Infinite iterators
-
repeat(value:)→ infinite iterator yielding value -
(0..).iter()→ infinite range from 0 -
(0.. by -1).iter()→ infinite descending (requires bound) - Must use
.take(count:)before.collect() - Rust Tests:
ori_llvm/src/collections/infinite_tests.rs
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.10) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.10 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.10: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.11 Lambda & Closure Support (verified 2026-03-29; corrected 2026-04-20 per §08)
-
Implement: Basic lambdas
- Simple lambda syntax:
x -> x + 1 - Multi-param lambdas:
(a, b) -> a + b - No-param lambdas:
() -> 42
- Simple lambda syntax:
-
Implement: Advanced lambda features
- Typed lambdas:
(x: int) -> int = x * 2 - Proper capture-by-value semantics
- Nested lambdas
- Lambda in lambda captures
- Default parameters in lambdas
- Typed lambdas:
-
Implement: Function references
- Function reference as value
- Higher-order function codegen
- Passing functions to other functions
- Named function → closure coercion — FIXED (
test_hof_apply_identity,test_hof_named_fn_as_argpass)
-
Fix: Closure ABI issues (all fixed, verified 2026-03-29)
-
(int) -> boolas function parameter — FIXED (test_hof_bool_lambdapasses) - Zero-arg closure capturing 3+ strings — FIXED (
test_depth_closure_capturing_multiple_stringspasses) -
.map(r -> r.score)closure accessing struct field — FIXED (test_stress_combined_struct_closure_iterationpasses)
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.11) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.11 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.11: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.12 Built-in Functions (verified 2026-03-29)
-
Implement: Basic built-ins
-
print(msg:) -
panic(msg:)→Never - Basic assertions
-
-
Implement: Comparison built-ins
-
compare(left:, right:)→Ordering -
min(left:, right:)with Comparable -
max(left:, right:)with Comparable
-
-
Implement: Collection built-ins
-
len(collection:)for all collection types -
is_empty(collection:) -
repeat(value:)→ infinite iterator -
hash_combine(seed:, value:)→ int
-
-
Implement: Developer built-ins
-
todo()/todo(reason:)→Never -
unreachable()/unreachable(reason:)→Never -
dbg(value:)/dbg(value:, label:)→T -
drop_early(value:) -
is_cancelled()→bool
-
-
Implement: Assertion built-ins
-
assert_some(option:),assert_none(option:) -
assert_ok(result:),assert_err(result:) -
assert_panics(f:) -
assert_panics_with(f:, msg:)
-
-
Implement: Option/Result methods
-
.map(transform:),.and_then(transform:) -
.unwrap_or(default:),.filter(predicate:) -
.ok_or(error:),.ok(),.err() -
.context(msg:)for Result -
.trace(),.trace_entries(),.has_trace()
-
-
Fix: Conversion method return type tracking (all fixed, verified 2026-03-29)
-
int.f()result type — FIXED (test_conv_int_f_shorthandpasses) -
int.byte()— FIXED (test_conv_int_to_byte_truncatespasses) -
int.byte().to_int()conversion chain — FIXED (test_conv_int_to_byte,test_conv_int_to_byte_max,test_conv_int_to_byte_to_intpass)
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.12) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.12 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.12: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.13 FFI Support
Related Proposals:
-
proposals/approved/platform-ffi-proposal.md -
Implement: C FFI
-
extern "c" from "lib" { ... }declaration codegen - C type bindings:
c_char,c_short,c_int,c_long,c_longlong - C type bindings:
c_float,c_double,c_size - Function name mapping with
as "native_name" -
CPtropaque pointer type (size_t sized) -
Option<CPtr>for nullable pointers (None = null) - C variadic functions:
extern "c" { @printf (fmt: CPtr, ...) -> c_int }- Parse variadic
...in extern function declarations - LLVM codegen: emit variadic function type (
fn_type(..., true)) - Argument promotion rules:
float→double,i8/i16→i32(C ABI) - Variadic calls only allowed for extern declarations (not user-defined)
- Parse variadic
- Library linking:
-l<lib>flag generation - Rust Tests:
ori_llvm/src/ffi/c_ffi_tests.rs
-
-
Implement: Unsafe expressions
-
unsafe { ... }block codegen (same as inner expr, marker only) -
uses FFIcapability requirement at call sites - Pointer operations:
ptr_read<T>(ptr:),ptr_write<T>(ptr:, value:) - Pointer arithmetic (future)
- Rust Tests:
ori_llvm/src/ffi/unsafe_tests.rs
-
-
Implement: JavaScript FFI (WASM target)
-
extern "js" { ... }declaration codegen -
extern "js" from "./file.js"imports with path resolution -
JsValuehandle type (index into JS heap slab) -
JsPromise<T>async handling - Implicit promise resolution at
letbinding sites - String marshalling: Ori str ↔ JS TextEncoder/TextDecoder
- Rust Tests:
ori_llvm/src/ffi/js_ffi_tests.rs
-
-
Implement: Memory layout control
-
#repr("c")struct attribute - C-compatible struct layout (field order, padding, alignment)
- Callback support: Ori functions as C function pointers
- Rust Tests:
ori_llvm/src/ffi/layout_tests.rs
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.13) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.13 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.13: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.14 Conditional Compilation
Related Proposals:
-
proposals/approved/conditional-compilation-proposal.md -
Implement: Target conditionals
-
#target(os: "linux")- compile only if target OS matches -
#target(arch: "x86_64")- compile only if arch matches -
#target(family: "unix")- compile only if family matches -
any_os: ["linux", "macos"]- compile if any match -
not_os: "windows"- compile if OS doesn’t match - File-level:
#!target(...)at top of file - Non-matching branches not emitted to object file
- Rust Tests:
ori_llvm/src/conditional/target_tests.rs
-
-
Implement: Config conditionals
-
#cfg(debug)- compile only in debug builds -
#cfg(release)- compile only in release builds -
#cfg(feature: "name")- compile if feature enabled -
any_feature: ["a", "b"]- compile if any feature enabled -
not_feature: "x"- compile if feature not enabled -
not_debug- compile only in release - Rust Tests:
ori_llvm/src/conditional/config_tests.rs
-
-
Implement: Compile-time constants
-
$target_os→"linux"|"macos"|"windows"| … -
$target_arch→"x86_64"|"aarch64"|"wasm32"| … -
$target_family→"unix"|"windows"|"wasm" -
$debug→truein debug builds,falseotherwise -
$release→truein release builds,falseotherwise - False branch not type-checked (dead code elimination)
- Rust Tests:
ori_llvm/src/conditional/const_tests.rs
-
-
Implement: Compile errors
-
compile_error("msg")emits error at compile time - Used with conditionals for unsupported configurations
- Rust Tests:
ori_llvm/src/conditional/error_tests.rs
-
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.14) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.14 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.14: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.15 Memory Management (ARC) (verified 2026-03-29 — ~290+ ARC/RC tests pass)
Related Proposals:
-
proposals/approved/drop-trait-proposal.md -
proposals/approved/memory-model-edge-cases-proposal.md -
proposals/approved/clone-trait-proposal.md -
Spec: Type classification in
15-memory-model.mdupdated to type-containment model (matchesori_arc) -
Implement: Reference counting (verified 2026-03-29 — 55 arc tests, 93 iter_rc_matrix tests, 50 rc_matrix tests pass)
- Heap allocation with atomic refcount header:
{ refcount: AtomicU64, data: T } -
fetch_add(1, Acquire)on clone/share -
fetch_sub(1, Release)on drop - Free when refcount reaches zero (after acquire fence)
- Stack-allocated values: no refcount (moved or copied)
- Rust Tests:
ori_llvm/src/arc/refcount_tests.rs
- Heap allocation with atomic refcount header:
-
Spec: Drop trait in
spec/08-types.md§ Drop Trait DONE- Trait definition, execution timing, LIFO order
- Constraints (no async, must return void, panic during unwind = abort)
- drop_early built-in function
-
Implement: Drop trait codegen (verified 2026-03-29)
- Detect types implementing
Droptrait - Generate destructor call when refcount reaches zero
- Destructor runs before memory reclamation
-
@drop (self) -> voidsignature - Drop cannot declare
uses Suspend(compile error) - Rust Tests:
ori_llvm/src/arc/drop_tests.rs
- Detect types implementing
-
Implement: Destruction ordering
- Local bindings: reverse declaration order
- Struct fields: reverse declaration order
- List elements: back-to-front (last element first)
- Tuple elements: right-to-left
(a, b, c)→ c, b, a - Map entries: unspecified order (no guarantees)
- Rust Tests:
ori_llvm/src/arc/order_tests.rs
-
Implement: Panic during destruction
- Single panic in destructor: propagate normally
- Other destructors still run after first panic
- Double panic (destructor panics during unwind): immediate abort
- Abort message: “panic during panic - aborting”
- Rust Tests:
ori_llvm/src/arc/panic_tests.rs
-
Implement: Early drop
-
drop_early(value:)built-in - Immediately decrements refcount and runs destructor if zero
- Value cannot be used after
drop_early - Compile error if value used after drop
- Rust Tests:
ori_llvm/src/arc/early_drop_tests.rs
-
-
Implement: Async destructor restriction
- Compile error if Drop.drop declares
uses Suspend - Error code and message for async destructor attempt
- Compile error if Drop.drop declares
-
Implement: Last-reference optimization (in-place mutation when RC=1)
- Detect
isUnique(ref)at runtime (refcount == 1) - When unique, reuse allocation for same-shape value instead of alloc+free
- Applies to struct update, map insert/remove, list push/pop
- Reference: Perceus paper §3.3 “Reuse Analysis”, Koka
CheckFBIP.hs - Rust Tests:
ori_llvm/tests/aot/arc.rs— last-reference reuse tests
- Detect
-
Implement: Reset/reuse optimization (constructing same-shape value after match)
- After pattern match deconstructs a value, reuse its allocation for newly constructed value of same type
- Emit
reset/reuseinstructions in canonical IR (Lean 4 / Koka pattern) - Only applies when matched value has RC=1 (exclusive ownership)
- Reference: Lean 4
ExpandResetReuse.lean, Perceus paper §3.4 - Rust Tests:
ori_llvm/tests/aot/arc.rs— reset/reuse tests
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.15) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.15 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.15: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.16 Optimization Passes (verified 2026-03-29)
21.16.1 Representation Optimization
Proposal: proposals/approved/representation-optimization-proposal.md
Formalize the compiler’s freedom to optimize machine representations while preserving semantic equivalence. Tier 1 and most Tier 2 optimizations are already implemented. All [x] items verified 2026-03-29 via 65 type_info unit tests + 36 narrowing integration tests.
- Tier 1: Type-Intrinsic Narrowing —
type_info/mod.rs-
bool→i1,byte→i8,char→i32,Ordering→i8 -
void→ zero-sized ori64(0) - Range inclusive flag →
i1
-
- Tier 2a: Enum Discriminant Narrowing —
type_info/mod.rs- All enum tags use
i8 - Dynamic tag width for >256 variants (i16/i32)
- All enum tags use
- Tier 2b: All-Unit Enum Elimination —
type_info/mod.rs- Enums with no payload variants omit payload array
- Tier 2c: Sum Type Payload Sharing —
lower_error_handling.rs- Result uses max(Ok, Err) payload slot
- Alloca+store+load coercion pattern with zero-initialization
- Tier 2d: ARC Elision —
type_info/mod.rs- Transitive triviality classification with cycle detection
- Two-level check: per-type conservative + transitive walk
- Tier 2e: Newtype Erasure — already specified in Types § Newtype
- Tier 2f: Struct Field Reordering — not implemented
- Alignment-aware field ordering to reduce padding
- Respect
#reprattribute constraints - Maintain declaration-order mapping for derived traits
- Tier 3: LLVM-Delegated Value Range Narrowing — future
- Emit
nsw/nuwflags on overflow-checked arithmetic - Emit
rangemetadata on loads with known value ranges - Emit
nonnull/dereferenceableattributes on pointers
- Emit
- Known Gaps:
- ABI size computation ignores struct field padding (
abi/mod.rs) -
TypeInfo::alignment()returns hardcoded values, not representation-aware
- ABI size computation ignores struct field padding (
21.16.2 LLVM Optimization Pipeline
-
Implement: Optimization pipeline
- Configure standard optimization levels (O0, O1, O2, O3)
- Enable inlining, dead code elimination, constant folding
- Loop optimizations
- Tail call optimization
-
Implement: Debug info generation
- Source location tracking
- Variable debug info
- Type debug info
- DWARF/CodeView emission
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.16) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.16 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.16: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.17 Runtime Support (verified 2026-03-29 — 360 tests pass, 0 failures)
-
Implement: Basic runtime functions
- Rust Tests:
tests/runtime_tests.rs -
ori_print,ori_print_int,ori_print_float,ori_print_bool -
ori_panic,ori_panic_cstr -
ori_assert,ori_assert_eq_int,ori_assert_eq_bool,ori_assert_eq_str -
ori_str_concat,ori_str_eq,ori_str_ne -
ori_str_from_int,ori_str_from_bool,ori_str_from_float -
ori_list_new,ori_list_free,ori_list_len -
ori_compare_int,ori_min_int,ori_max_int
- Rust Tests:
-
Implement: Extended runtime
- Map runtime functions
- Set runtime functions
- Channel runtime functions
- Duration/Size runtime functions
- Stack trace capture functions
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. -
Subsection close-out (21.17) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.17 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.17: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.18 Architecture (Reference)
The LLVM backend follows Rust’s rustc_codegen_llvm patterns:
Context Hierarchy
// Simple context - just LLVM types
pub struct SimpleCx<'ll> {
pub llcx: &'ll Context,
pub llmod: Module<'ll>,
pub ptr_type: PointerType<'ll>,
pub isize_ty: IntType<'ll>,
}
// Full context - adds Ori-specific state
pub struct CodegenCx<'ll, 'tcx> {
pub scx: SimpleCx<'ll>,
pub interner: &'tcx StringInterner,
pub instances: RefCell<HashMap<Name, FunctionValue<'ll>>>,
pub type_cache: RefCell<TypeCache<'ll>>,
}
Builder Pattern
pub struct Builder<'a, 'll, 'tcx> {
llbuilder: &'a inkwell::builder::Builder<'ll>,
cx: &'a CodegenCx<'ll, 'tcx>,
}
Directory Structure
ori_llvm/src/
├── lib.rs # Crate root, re-exports
├── context.rs # SimpleCx, CodegenCx, TypeCache
├── builder.rs # Builder + expression compilation
├── types.rs # Type mapping helpers
├── declare.rs # Function declaration
├── traits.rs # BackendTypes, BuilderMethods traits
├── module.rs # ModuleCompiler (two-phase codegen)
├── runtime.rs # Runtime FFI functions
├── evaluator.rs # JIT evaluator (OwnedLLVMEvaluator)
├── operators.rs # Binary/unary operator codegen
├── control_flow.rs # if/else, loops, break/continue
├── matching.rs # Pattern matching codegen
├── collections/ # Collection codegen (tuples, structs, lists)
│ ├── mod.rs
│ ├── tuples.rs
│ ├── structs.rs
│ ├── lists.rs
│ └── option_result.rs
├── functions/ # Function codegen
│ ├── mod.rs
│ ├── body.rs # Function body compilation
│ ├── calls.rs # Function call codegen
│ ├── lambdas.rs # Lambda/closure codegen
│ ├── builtins.rs # Built-in function codegen
│ ├── sequences.rs # FunctionSeq (run, try, match)
│ └── expressions.rs # FunctionExp (recurse, print, panic)
└── tests/ # Unit tests
├── mod.rs
├── arithmetic_tests.rs
├── collection_tests.rs
├── control_flow_tests.rs
├── function_tests.rs
├── matching_tests.rs
└── ...
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. - Subsection close-out (21.18) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.18 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.18: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
21.19 Section Completion Checklist (verified 2026-03-29)
Infrastructure:
- JIT compilation working
- All current Ori tests pass via LLVM
- All Rust unit tests pass (466/466 lib, 0 ignored; verified 2026-03-29)
- Architecture follows Rust patterns
- Unified import pipeline (imports resolved once, compiled into JIT module)
- Generic monomorphization (verified 2026-03-29 — 33 generics tests pass)
- AOT compilation (see Section 21B)
Type System:
- Primitive types
- Option/Result (basic)
- Lists (basic)
- Duration/Size types (partial — basic arithmetic works, methods not implemented)
- Newtypes
- Sum types (general)
- Fixed-capacity lists
- Channels
- Maps (full support)
- Sets
Expressions:
- Basic expressions
- Binary/unary operators (primitives)
- Range with step (
by) - Spread operator (
...) (struct spread works; list/map spread status unclear) - Coalesce operator (
??) - Floor division (
div) - Type conversions (
as,as?) - Complex assignments
Control Flow:
- Basic if/else, loops
- Labeled loops
- Break with values
- For-yield expressions
- Try/catch patterns
Traits & Dispatch:
- Associated functions
- Operator trait dispatch
- Iterator trait methods (partial — map/filter/fold/collect/take/chain work)
- Comparison trait methods
Concurrency:
- Parallel pattern
- Spawn pattern
- Channels
- Nursery pattern
Capabilities:
- Capability tracking
- With pattern provision
- Default implementations
FFI:
- C FFI
- JavaScript FFI
- Unsafe blocks
Memory:
- ARC implementation
- Drop trait
- Destruction ordering
Optimization:
- Representation optimization (Tiers 1-2e done)
- LLVM optimization pipeline
- Debug info generation
Verified AOT Gaps (from Section 11.1 verification, updated 2026-02-23):
Resolved:
- Derive Eq struct codegen:
emit_comparison_via_traitnow dispatches to derivedeqmethod for non-primitive types instead of falling through to scalaricmp - Derive Comparable struct codegen:
emit_ordering_comparisonnow dispatches to derivedcomparemethod and checks Ordering result (0=Less, 1=Equal, 2=Greater) for</>/<=/>= - ARC enum basic drop and string-payload drop:
test_arc_enum_basic_dropandtest_arc_enum_with_string_payloadun-ignored and passing
Resolved (verified 2026-03-29):
- List mutation methods in AOT builtin table — FIXED (
test_aot_list_push,test_aot_list_first_lastpass) - Map methods in AOT builtin table — FIXED (
test_aot_map_is_emptypasses) -
list[index]subscript resolved — FIXED (test_aot_list_indexpasses) - Closure-returning-closure type inference — FIXED (
test_aot_closure_capturing_closurepasses) - Generic monomorphization in ARC pipeline — FIXED (33 generics tests pass)
-
catch(expr:)lowered through ARC pipeline — FIXED (9 catch tests pass) - String interpolation — FIXED (
test_aot_string_interpolationpasses)
Open:
- Enum variant constructors not declared as LLVM functions (no test found by listed name, but many enum tests pass via derives and pattern matching)
-
/tpr-reviewpassed — independent Codex review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — implementation hygiene review clean (phase boundaries, SSOT, algorithmic DRY, naming). MUST run AFTER/tpr-reviewis clean. -
/improve-toolingretrospective completed — MANDATORY at section close, after both reviews are clean. Reflect on the section’s debugging journey (whichdiagnostics/scripts you ran, which command sequences you repeated, where you added ad-hocdbg!/tracingcalls, 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.
Cross-references to existing items:
- Generic monomorphization → § 21.7 — RESOLVED (verified 2026-03-29)
- Enum variant constructors → § 21.2 (blocks enums, recursive types)
catch(expr:)→ § 21.5 — RESOLVED (verified 2026-03-29)- String interpolation → § 21.3 — RESOLVED (verified 2026-03-29)
New AOT tests added (2026-02-23, 13 tests, all passing): derive_eq_struct (un-ignored), derive_eq_struct_not_equal, derive_eq_struct_with_strings, derive_comparable_struct (4 comparisons: <, >, <=, >=), panic_basic, option_unwrap_some, result_unwrap_ok, struct_with_list_and_string, nested_struct_with_strings, for_yield_with_filter, for_yield_transform
New AOT test files added (2026-02-23, Section 11.1 verification — 5 files, 117 tests total):
error_handling.rs— 21 tests (21 pass, 0 ignore): Result/Option basics,?operator, chaining, deep chainshigher_order.rs— 27 tests (23 pass, 4 ignore): HOF apply, composition, closures with captures, nested closures, foldtuples.rs— 29 tests (23 pass, 6 ignore): construction, destructuring, field access, as param/return, nested, strings, closuresstructs.rs— 29 tests (28 pass, 1 ignore): construction, string fields, update syntax, nested, as param/return, closures, derived Eqrecursion.rs— 22 tests (22 pass, 0 ignore): factorial, fibonacci, tail-recursive, mutual, with Result/Option/match, depth tests
Total AOT test counts (verified 2026-03-29): 1977 passed, 0 failed, 17 ignored
Remaining known bugs (verified 2026-03-29):
- Catch type inference:
catch()returnsResult<() -> T, str>instead ofResult<T, str>— blocks 12 AOT tests (type checker bug, not LLVM) - Inline panic in catch:
invokeonly intercepts callee-function panics, not same-function inline code — blocks 1 test - Chained tuple field access:
t.0.1lexed as float by parser — blocks 2 tests (parser bug, not LLVM; tracked in Section 05) - Nounwind analysis: does not distinguish may-unwind monomorphized callees — blocks 1 test
Exit Criteria: Feature parity with evaluator for all language constructs
-
/tpr-reviewpassed — independent review found no critical or major issues (or all findings triaged) -
/impl-hygiene-reviewpassed — hygiene review clean. MUST run AFTER/tpr-reviewis clean. - Subsection close-out (21.19) — MANDATORY before starting the next subsection. Run
/improve-toolingretrospectively on THIS subsection’s debugging journey (per.claude/skills/improve-tooling/SKILL.md“Per-Subsection Workflow”): whichdiagnostics/scripts you ran, where you addeddbg!/tracingcalls, 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-pushusing a valid conventional-commit type (build(diagnostics): ... — surfaced by section-21.19 retrospective—build/test/chore/ci/docsare valid;tools(...)is rejected by the lefthook commit-msg hook). Mandatory even when nothing felt painful. If genuinely no gaps, document briefly: “Retrospective 21.19: no tooling gaps”. Update this subsection’sstatusin section frontmatter tocomplete. -
/sync-claudesection-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 --checkand clean any detected temp files.
Running Tests
# LLVM is a default feature — no Docker required (verified 2026-03-29)
# Build all (includes LLVM)
cargo b
# Run all tests (Rust unit + AOT integration + spec)
./test-all.sh
# Run LLVM-specific tests
cargo test -p ori_llvm --lib # 466 unit tests
cargo test -p ori_llvm --test aot_tests # 1977 AOT integration tests
# Run spec tests only
cargo st
# Run with debug output
ORI_DEBUG_LLVM=1 ori test tests/spec/types/primitives.ori
# Legacy Docker workflow still works but is not required:
# ./docker/llvm/build.sh && ./docker/llvm/run.sh ori test