Skip to content

generics: VM/Cranelift type-param-aware dispatch (ILO-387)#635

Merged
danieljohnmorris merged 5 commits into
mainfrom
feature/generics-vm-jit
May 22, 2026
Merged

generics: VM/Cranelift type-param-aware dispatch (ILO-387)#635
danieljohnmorris merged 5 commits into
mainfrom
feature/generics-vm-jit

Conversation

@danieljohnmorris
Copy link
Copy Markdown
Collaborator

Summary

  • Confirmed generics are already working on both engines: type parameters are erased at compile time (no boxing/unboxing), so the bytecode VM and Cranelift JIT execute generic functions as monomorphic code without any dispatch table changes needed.
  • Added 7 bytecode VM regression tests (vm::tests) covering comparable, numeric, and unbounded (any) type-parameter bounds with both numeric and text concrete types at call sites.
  • Added 5 Cranelift JIT regression tests (vm::jit_cranelift) covering the same bound kinds to lock in JIT correctness.

Closes ILO-387. Extends ILO-61 (#620), builds on ILO-385 (#628).

Test plan

  • cargo test vm_bounded_generic — 7 tests pass
  • cargo test cranelift_bounded_generic — 5 tests pass
  • cargo test -- --skip aot_binary_size — all tests pass (aot_binary_size and cli_verbs AOT tests require a pre-built libilo.a and are pre-existing failures unrelated to this PR)

🤖 Generated with Claude Code

@codecov
Copy link
Copy Markdown

codecov Bot commented May 22, 2026

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
3531 1 3530 0
View the full list of 1 ❄️ flaky test(s)
ilo::cli_trace::trace_demo_bindings_contain_expected_vars

Flake rate in main: 100.00% (Passed 0 times, Failed 7 times)

Stack Traces | 0.012s run time
thread 'trace_demo_bindings_contain_expected_vars' (39583) panicked at tests/cli_trace.rs:69:5:
expected exit 0
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

@danieljohnmorris
Copy link
Copy Markdown
Collaborator Author

needs manual rebase (conflicts after partial auto-resolve in: )

@danieljohnmorris
Copy link
Copy Markdown
Collaborator Author

needs manual — rebase conflict in non-doc file(s)

@danieljohnmorris danieljohnmorris force-pushed the feature/generics-vm-jit branch 2 times, most recently from 3252997 to 62f5ff1 Compare May 22, 2026 11:06
Daniel Morris and others added 5 commits May 22, 2026 17:17
Add explicit generic type parameters with bound constraints to ilo
function signatures. The verifier now enforces cross-call-site type
variable consistency and bound satisfaction, closing the soundness hole
where `fn id a>a` silently accepted inconsistent types at different call
sites.

MVP:
- Parser: `name<a:bound ...>` block after fn name; `<a>` unbounded
- Bounds: any (default), comparable (n/t/b), numeric (n), text (t)
- Verifier: unifies type variable bindings per call site (ILO-T044)
- Backward compatible: legacy `fn x:a>a;x` style unchanged
- New error codes: ILO-T044 (inconsistency/bound violation), ILO-P022
  (malformed type-param block)
- `examples/generics-bounded.ilo` passes on tree engine
- 7 new verify tests; all 3330+ existing tests green

Deferred: variance, higher-kinded types, multiple-bound conjunctions,
bound inference from usage, return-type generic substitution, VM/JIT
type-param-aware dispatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Generics are erased at compile time — no boxing or unboxing occurs — so
the bytecode VM and Cranelift JIT already dispatch generic functions
correctly as monomorphic code. Add regression tests in vm::tests (7 VM
tests) and vm::jit_cranelift (5 JIT tests) covering comparable, numeric,
and unbounded (any) type-parameter bounds, exercising both numeric and
text concrete types at call sites. Also documents the compile-time erasure
strategy so it is clear future changes do not need dynamic dispatch.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a function has explicit type_params (e.g. `gid<a> x:a>a`), the
verifier now infers the concrete return type at each call site by
substituting the type-variable bindings collected from the arguments.

Previously `gid 5` produced `Ty::Unknown`; it now correctly produces
`Ty::Number`, enabling downstream type-checking to catch mismatches
(ILO-T007) when the return value is passed to typed contexts.

- Add `original_return: ast::Type` to `FuncSig` to carry the AST
  return type alongside the already-stored `original_params`
- Add `collect_type_var_bindings` to extract bindings from compound
  param shapes (`L a`, `M t a`, `R a t`, etc.)
- Add `subst_return_ty` to recursively substitute type-variable letters
  in the return type using the collected bindings
- Hoist `var_bindings` out of the `if has_explicit_bounds` block so
  it is available for return-type substitution in all cases
- Add 4 regression tests covering: number identity, text identity,
  type mismatch detection, and list-element extraction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@danieljohnmorris danieljohnmorris force-pushed the feature/generics-vm-jit branch from 6e11105 to 16a7bc2 Compare May 22, 2026 16:21
@danieljohnmorris
Copy link
Copy Markdown
Collaborator Author

mini pc is reviewing this

@danieljohnmorris danieljohnmorris merged commit e966650 into main May 22, 2026
7 of 11 checks passed
@danieljohnmorris danieljohnmorris deleted the feature/generics-vm-jit branch May 22, 2026 16:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant