Skip to content

Use global impl registry and ban bare Self in associated type defaults - #4251

Merged
2kai2kai2 merged 2 commits into
canaryfrom
kai/fix-reflect-implements
Jul 28, 2026
Merged

2kai2kai2 merged 2 commits into
canaryfrom
kai/fix-reflect-implements

Conversation

@2kai2kai2

@2kai2kai2 2kai2kai2 commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Does two things:

  1. the runtime now uses a global interface implementations registry instead of only searching the interface and target's registries. This handles the case where the orphan rule permits impls of non-local types based on local generic bounds.
  2. the compiler now bans the presence of Self in associated type defaults (except as an associated type projection's base). This is because inclusion in defaults would cause an unresolved Self in interface-existential types which is unsound since we don't know the concrete implementor type.

Summary by CodeRabbit

  • New Features
    • Operators now require explicit Output result types for add/subtract/multiply/divide/remainder and negate across numeric, string, and custom types.
    • Improved interface/implementation resolution using a program-wide package index for consistent behavior in multi-package projects.
  • Bug Fixes
    • Added a dedicated compiler diagnostic (E0157) when an invalid bare Self is used as an associated-type default, while continuing to allow valid Self projections and concrete defaults.
  • Tests
    • Extended operator and interface well-formedness test coverage for these result-type and Self-default rules.

@vercel

vercel Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
beps Ready Ready Preview, Comment Jul 28, 2026 9:58pm
promptfiddle Ready Ready Preview, Comment Jul 28, 2026 9:58pm
promptfiddle2 Ready Ready Preview, Comment Jul 28, 2026 9:58pm

Request Review

@github-actions

Copy link
Copy Markdown

⏭️ Performance benchmarks were skipped

Perf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to canary/main.

To run them on this PR, do any of the following, then push a commit (or re-run CI):

  • Add RUN_CODSPEED=1 to the PR description, or
  • Include run-perf or /perf in the PR title or any commit message.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ce2fe4c2-6b65-4dc4-b9a7-35bc6ef5317f

📥 Commits

Reviewing files that changed from the base of the PR and between b8bf7e5 and 1af6896.

⛔ Files ignored due to path filters (1)
  • baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snap is excluded by !**/*.snap
📒 Files selected for processing (14)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/math.baml
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_tir/src/infer_context.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_compiler_diagnostics/src/diagnostic.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_tests/baml_src/ns_operators/operators.baml
  • baml_language/crates/baml_tests/tests/interfaces.rs
  • baml_language/crates/bex_engine/src/lib.rs
  • baml_language/crates/bex_vm/src/package_baml/resolve.rs
  • baml_language/crates/bex_vm/src/package_baml/type_class.rs
  • baml_language/crates/bex_vm/src/package_load.rs
  • baml_language/crates/bex_vm/src/vm.rs
🚧 Files skipped from review as they are similar to previous changes (12)
  • baml_language/crates/baml_compiler_diagnostics/src/diagnostic.rs
  • baml_language/crates/baml_tests/tests/interfaces.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/bex_vm/src/package_baml/type_class.rs
  • baml_language/crates/baml_tests/baml_src/ns_operators/operators.baml
  • baml_language/crates/bex_engine/src/lib.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs
  • baml_language/crates/baml_compiler2_tir/src/infer_context.rs
  • baml_language/crates/bex_vm/src/package_baml/resolve.rs
  • baml_language/crates/bex_vm/src/package_load.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/math.baml

📝 Walkthrough

Walkthrough

The PR requires explicit operator output types, rejects bare Self in associated-type defaults with diagnostic E0157, and introduces a shared program-wide package index for VM implementation resolution.

Changes

Operator typing and diagnostics

Layer / File(s) Summary
Explicit operator output contracts
baml_language/crates/baml_builtins2/.../math.baml, baml_language/crates/baml_tests/...
Operator interfaces now require explicit Output types, and primitive and user-defined implementations declare concrete results.
Associated-type default validation
baml_language/crates/baml_compiler2_tir/..., baml_language/crates/baml_compiler_diagnostics/..., baml_language/crates/baml_lsp2_actions/...
Bare Self in associated-type defaults produces SelfInAssociatedTypeDefault and diagnostic code E0157.
Self default regression coverage
baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
Tests cover rejected bare or nested Self and accepted projections or concrete defaults.

Program-wide implementation indexing

Layer / File(s) Summary
PackageIndex construction
baml_language/crates/bex_vm/src/package_load.rs
Package loading builds a shared index of package pointers and interface-keyed implementation rules.
Engine and VM index wiring
baml_language/crates/bex_engine/src/lib.rs, baml_language/crates/bex_vm/src/vm.rs
The engine and VMs store and pass PackageIndex for package and built-in type lookups.
Program-wide implementation resolution
baml_language/crates/bex_vm/src/package_baml/*
Resolution, proof, and implementor reflection use implementation rules aggregated across packages.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ProgramLoader
  participant PackageIndex
  participant BexEngine
  participant BexVm
  participant resolve_implements_rule
  ProgramLoader->>PackageIndex: build package and interface rule indexes
  ProgramLoader->>BexEngine: return heap and PackageIndex
  BexEngine->>BexVm: construct VM with shared PackageIndex
  BexVm->>resolve_implements_rule: resolve interface implementation
  resolve_implements_rule->>PackageIndex: retrieve rules for interface
  PackageIndex-->>resolve_implements_rule: return program-wide rules
Loading

Possibly related PRs

Suggested reviewers: codeshaunted

Poem

I’m a rabbit with outputs, precise and bright,
Setting each operator’s result just right.
Bare Self gets a warning in the burrow,
While package rules gather without sorrow.
Across every VM, the indexes align—
Hop, hop, the types compile fine!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: global impl registry lookup and banning bare Self in associated type defaults.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch kai/fix-reflect-implements
🔧 Fix failing CI
  • Fix failing CI in branch kai/fix-reflect-implements

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
baml_language/crates/bex_vm/src/package_baml/resolve.rs (1)

43-56: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Missing dedicated regression tests for the new program-wide impl-resolution semantics.

This PR introduces a behavior change — cross-package impl resolution keyed by a program-wide PackageIndex — but neither the new data structure nor the resolution algorithm it feeds has a unit test in the reviewed files covering the specific scenario the PR targets (an impl anchored in a package that owns neither Self nor the interface).

  • baml_language/crates/bex_vm/src/package_baml/resolve.rs#L43-L56: add a unit test exercising rules_for/resolve_implements_rule for an impl declared in a third package (owning neither the receiver type nor the interface).
  • baml_language/crates/bex_vm/src/package_load.rs#L84-L136: add a unit test for PackageIndex.impl_rules/impl_rules_of accumulating rules for the same interface across two distinct packages.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@baml_language/crates/bex_vm/src/package_baml/resolve.rs` around lines 43 -
56, The new program-wide impl-resolution behavior lacks regression coverage. In
baml_language/crates/bex_vm/src/package_baml/resolve.rs:43-56, add a unit test
covering rules_for and resolve_implements_rule when the impl is declared in a
third package that owns neither the receiver type nor the interface. In
baml_language/crates/bex_vm/src/package_load.rs:84-136, add a unit test
verifying PackageIndex.impl_rules and impl_rules_of accumulate rules for the
same interface from two distinct packages.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@baml_language/crates/baml_compiler2_tir/src/inference.rs`:
- Around line 2202-2206: The Self detector used by the default validation in
inference.rs around TypeInferenceBuilder::type_ref_contains_bare_self must
recurse into associated-type projection bases, exempting only an exact Self base
so nested forms such as (Self[] as I).Item are rejected. Add a regression test
in lower_type_expr.rs in the existing test area covering a default like type Out
= (Self[] as I).Item and asserting the expected rejection.

---

Nitpick comments:
In `@baml_language/crates/bex_vm/src/package_baml/resolve.rs`:
- Around line 43-56: The new program-wide impl-resolution behavior lacks
regression coverage. In
baml_language/crates/bex_vm/src/package_baml/resolve.rs:43-56, add a unit test
covering rules_for and resolve_implements_rule when the impl is declared in a
third package that owns neither the receiver type nor the interface. In
baml_language/crates/bex_vm/src/package_load.rs:84-136, add a unit test
verifying PackageIndex.impl_rules and impl_rules_of accumulate rules for the
same interface from two distinct packages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: aa59d7ac-2dfc-4056-905b-ca6d8f3c068d

📥 Commits

Reviewing files that changed from the base of the PR and between 384a6ff and b8bf7e5.

⛔ Files ignored due to path filters (1)
  • baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snap is excluded by !**/*.snap
📒 Files selected for processing (13)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/math.baml
  • baml_language/crates/baml_compiler2_tir/src/infer_context.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_compiler_diagnostics/src/diagnostic.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_tests/baml_src/ns_operators/operators.baml
  • baml_language/crates/baml_tests/tests/interfaces.rs
  • baml_language/crates/bex_engine/src/lib.rs
  • baml_language/crates/bex_vm/src/package_baml/resolve.rs
  • baml_language/crates/bex_vm/src/package_baml/type_class.rs
  • baml_language/crates/bex_vm/src/package_load.rs
  • baml_language/crates/bex_vm/src/vm.rs

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle July 28, 2026 20:40 Inactive
@github-actions

github-actions Bot commented Jul 28, 2026 •

Copy link
Copy Markdown

Binary size checks passed

✅ 7 passed

Artifact Platform File Gzip Gated on Baseline Delta Status
✅ baml-cli Linux 🔒 27.3 MB 11.6 MB file 27.3 MB -3.5 KB (-0.0%) OK
✅ packed-program Linux 🔒 17.7 MB 7.3 MB file 17.7 MB +12.3 KB (+0.1%) OK
✅ baml-cli macOS 🔒 21.2 MB 10.1 MB file 21.2 MB +32 B (+0.0%) OK
✅ packed-program macOS 🔒 13.9 MB 6.4 MB file 13.9 MB +32 B (+0.0%) OK
✅ baml-cli Windows 🔒 22.9 MB 10.4 MB file 22.9 MB -1.0 KB (-0.0%) OK
✅ packed-program Windows 🔒 14.8 MB 6.5 MB file 14.8 MB +2.6 KB (+0.0%) OK
✅ bridge_wasm WASM 16.6 MB 🔒 4.5 MB gzip 4.5 MB +8.8 KB (+0.2%) OK

🔒 = the size this artifact is GATED on (ceiling + delta). Binaries gate on file size (installed binary); WASM gates on gzip (download size). The other size is shown for information only.


Generated by cargo size-gate · workflow run

Since orphan rule permits impls with certain local generics even if
neither target is local we cannot just rely on the two packages when
looking up impls with generics. For simplicity we now do a global
search.
It breaks the interface-existential since `Self` is meaningless when we
don't know the implementor type. This is similar to rust and is the
reason they require `Output` to be explicitly declared for ops.
@2kai2kai2
2kai2kai2 force-pushed the kai/fix-reflect-implements branch from b8bf7e5 to 1af6896 Compare July 28, 2026 21:36
@2kai2kai2
2kai2kai2 enabled auto-merge July 28, 2026 21:36
@vercel
vercel Bot temporarily deployed to Preview – beps July 28, 2026 21:38 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 July 28, 2026 21:45 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle July 28, 2026 21:58 Inactive
@2kai2kai2
2kai2kai2 added this pull request to the merge queue Jul 28, 2026
Merged via the queue into canary with commit 78bb03e Jul 28, 2026
147 of 149 checks passed
@2kai2kai2
2kai2kai2 deleted the kai/fix-reflect-implements branch July 28, 2026 22:26

This branch was previously deployed

3 inactive deployments
Preview – promptfiddle — 1af68966 Deployed Jul 28, 2026 by vercel[bot]
Preview – promptfiddle2 — 1af68966 Deployed Jul 28, 2026 by vercel[bot]
Preview – beps — 1af68966 Deployed Jul 28, 2026 by vercel[bot]
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