Skip to content

Use indexed generic parameter identities - #4185

Merged
codeshaunted merged 15 commits into
canaryfrom
avery/b-896
Jul 28, 2026
Merged

Use indexed generic parameter identities#4185
codeshaunted merged 15 commits into
canaryfrom
avery/b-896

Conversation

@codeshaunted

@codeshaunted codeshaunted commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Issue Reference

Changes

  • Add one canonical, parent-linked TIR GenericEnv, modeled after rustc's ty::Generics.
  • Store each scope's own GenericParam { index, name, bound } instead of parallel vectors and manual parent merges.
  • Use the same environment for inference and generic-bound lowering across classes, interfaces, free impls, methods, and lambdas.
  • Preserve enclosing T while lowering D extends Driver<Task<T>>, fixing the associated projection in B-896.
  • Keep Ty::TypeVar name-based; this PR does not change runtime types or serialization.
  • Add the exact B-896 regression test.

Testing

  • cargo fmt --check --package baml_compiler2_tir --package baml_tests
  • cargo clippy -p baml_compiler2_tir --tests -- -D warnings
  • cargo test -p baml_compiler2_tir --lib (276 passed, 2 ignored)
  • cargo test -p baml_tests --test interfaces_class_generics (34 passed)
  • cargo test -p baml_tests --test interfaces_associated_types (130 passed, 1 ignored)
  • cargo test -p baml_tests --test interfaces (486 passed, 2 ignored)

Summary by CodeRabbit

  • New Features

    • Improved generic type handling with identity-preserving type parameters (indexed type variables) for more accurate inference and substitution.
    • Added a unified generic-scope environment model to power associated-type defaults, interface constraints, and generic throws.
    • Propagated indexed type-variable data through serialization and cross-language SDK interoperability.
    • Improved runtime handling of explicit type arguments across calls, closures, and virtual dispatch.
  • Bug Fixes

    • Fixed associated-type default/bounds realization and inherited default Self/frame handling.
    • Improved contextual lambda effect and exception (throws) inference.
  • Tests

    • Added/updated compiler and BAML test coverage for the above behaviors.

@linear

linear Bot commented Jul 24, 2026

Copy link
Copy Markdown

B-896

@vercel

vercel Bot commented Jul 24, 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 27, 2026 11:57pm
promptfiddle Ready Ready Preview, Comment Jul 27, 2026 11:57pm
promptfiddle2 Ready Ready Preview, Comment Jul 27, 2026 11:57pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 24, 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: 46586edb-46d1-4e29-9fb8-de4dea02488c

📥 Commits

Reviewing files that changed from the base of the PR and between 28f8f8f and 35fb984.

⛔ Files ignored due to path filters (1)
  • baml_language/crates/baml_tests/snapshots/baml_src/interfaces_class_generics.snap is excluded by !**/*.snap
📒 Files selected for processing (1)
  • baml_language/crates/baml_tests/baml_src/ns_interfaces_class_generics/interfaces_class_generics.baml
🚧 Files skipped from review as they are similar to previous changes (1)
  • baml_language/crates/baml_tests/baml_src/ns_interfaces_class_generics/interfaces_class_generics.baml

📝 Walkthrough

Walkthrough

This PR replaces name-based generic type-variable handling with indexed ParamTy identities across type representation, compiler environments, inference, lowering, runtime templates, VM calls, bridge serialization, SDK generation, and associated-type tests.

Changes

ParamTy generic identity

Layer / File(s) Summary
Type identity and generic environments
baml_language/crates/baml_type/*, baml_language/crates/baml_compiler2_tir/src/generic_env.rs
Introduces indexed ParamTy values, runtime generic layouts, parent-linked generic environments, and identity-keyed bounds and substitutions.
TIR inference and interface lowering
baml_language/crates/baml_compiler2_tir/src/{lower_type_expr.rs,inference.rs,interfaces.rs,generics.rs,unify.rs}, baml_language/crates/baml_compiler2_tir/src/builder/*
Migrates type-variable resolution, bounds, associated-type defaults, interface matching, unification, call inference, and throws instantiation to ParamTy keys.
Emission and runtime propagation
baml_language/crates/baml_compiler2_emit/*, baml_language/crates/baml_compiler2_mir/*, baml_language/crates/bex_vm/*, baml_language/crates/baml_type_runtime/*
Threads indexed generic parameters through emitted signatures, MIR templates, VM call frames, runtime inference, and type-argument extraction.
Wire formats and validation
baml_language/crates/bridge_ctypes/*, baml_language/sdks/*, baml_language/crates/baml_tests/*
Adds serialized type-variable indices, updates generated bridge bindings and SDK fixtures, and adds associated-type, generic-interface, and lambda-effects tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Poem

A rabbit hops through types unseen,
With indexed vars in every scene.
Bounds align and frames now flow,
Calls remember what they know.
“ParamTy!” cries the hare with glee—
Identity keeps generics free!

🚥 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 matches the core refactor: generic parameters now use indexed identities across lowering and inference.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch avery/b-896

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.

@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 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.

🧹 Nitpick comments (2)
baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs (1)

994-1036: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the interface and free-impl scope branches with regression tests.

The supplied regression covers a class-owned method, while this helper also adds interface Self and free-impl generics. Add focused cases for those branches, or verify existing tests cover them.

🤖 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/baml_compiler2_tir/src/lower_type_expr.rs` around lines
994 - 1036, Add regression coverage for function_in_scope_generic_params
covering an interface-owned method, asserting interface generics followed by the
implicit Self and function generics, and a free-impl method, asserting impl
generics followed by function generics. Reuse existing test helpers and verify
ordering matches the helper’s contract.
baml_language/crates/baml_tests/tests/interfaces_class_generics.rs (1)

781-805: 📐 Maintainability & Code Quality | 🔵 Trivial

Run cargo test --lib from the Cargo workspace root before merge.

This PR touches Rust; running cargo test --lib from the appropriate Cargo.toml directory needs to pass before the PR can land.

cargo test --lib must run from a directory containing the workspace Cargo.toml.

🤖 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/baml_tests/tests/interfaces_class_generics.rs` around
lines 781 - 805, Run cargo test --lib from the Rust workspace root containing
the workspace Cargo.toml, and ensure the test suite passes before merging the
change to method_generic_associated_projection_preserves_enclosing_class_param.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs`:
- Around line 994-1036: Add regression coverage for
function_in_scope_generic_params covering an interface-owned method, asserting
interface generics followed by the implicit Self and function generics, and a
free-impl method, asserting impl generics followed by function generics. Reuse
existing test helpers and verify ordering matches the helper’s contract.

In `@baml_language/crates/baml_tests/tests/interfaces_class_generics.rs`:
- Around line 781-805: Run cargo test --lib from the Rust workspace root
containing the workspace Cargo.toml, and ensure the test suite passes before
merging the change to
method_generic_associated_projection_preserves_enclosing_class_param.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f0caa1c9-20d7-44ac-92b9-ad0ccaa21898

📥 Commits

Reviewing files that changed from the base of the PR and between 25360a3 and 7910dfa.

📒 Files selected for processing (2)
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_tests/tests/interfaces_class_generics.rs

@github-actions

github-actions Bot commented Jul 24, 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 +39.7 KB (+0.1%) OK
packed-program Linux 🔒 17.7 MB 7.3 MB file 17.7 MB +35.2 KB (+0.2%) OK
baml-cli macOS 🔒 21.2 MB 10.1 MB file 21.2 MB +33.1 KB (+0.2%) OK
packed-program macOS 🔒 13.8 MB 6.4 MB file 13.8 MB +16.6 KB (+0.1%) OK
baml-cli Windows 🔒 22.9 MB 10.4 MB file 22.8 MB +41.0 KB (+0.2%) OK
packed-program Windows 🔒 14.8 MB 6.5 MB file 14.7 MB +40.3 KB (+0.3%) OK
bridge_wasm WASM 16.6 MB 🔒 4.5 MB gzip 4.5 MB +18.6 KB (+0.4%) 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

@codeshaunted codeshaunted changed the title Fix inherited generics in method bounds Refactor TIR generic environments and fix inherited bounds Jul 24, 2026

@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/baml_compiler2_tir/src/inference.rs (1)

1513-1514: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the redundant .clone() on GenericEnv. The function/class/interface constructors return GenericEnv<'db> by value, and the type derives Clone, so these .clone() calls are unnecessary no-ops.

  • baml_language/crates/baml_compiler2_tir/src/inference.rs#L1532-L1533
  • baml_language/crates/baml_compiler2_tir/src/inference.rs#L2263-L2263
  • baml_language/crates/baml_compiler2_tir/src/inference.rs#L2432-L2432
🤖 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/baml_compiler2_tir/src/inference.rs` around lines 1513 -
1514, Remove the redundant clone calls on GenericEnv returned by the
constructors used in inference.rs. Update the sites at
baml_language/crates/baml_compiler2_tir/src/inference.rs:1513-1514, 2245-2245,
and 2413-2413 by using the returned value directly while preserving the existing
generic environment behavior.
🤖 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/generic_env.rs`:
- Around line 304-318: Update the free impl branch of GenericEnv::from_sources
to preserve every GenericParamData::bounds entry as an interface intersection
bound instead of using only bounds.first(). Reuse the existing multi-bound
lowering path used by the impl resolver, and apply the same correction in the
MIR generic scope builder so free impl generics retain all BEP-044 bounds.

---

Nitpick comments:
In `@baml_language/crates/baml_compiler2_tir/src/inference.rs`:
- Around line 1513-1514: Remove the redundant clone calls on GenericEnv returned
by the constructors used in inference.rs. Update the sites at
baml_language/crates/baml_compiler2_tir/src/inference.rs:1513-1514, 2245-2245,
and 2413-2413 by using the returned value directly while preserving the existing
generic environment behavior.
🪄 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: bf973c19-3ba7-4b20-b740-5ab1478da908

📥 Commits

Reviewing files that changed from the base of the PR and between 7910dfa and b4ef530.

📒 Files selected for processing (5)
  • baml_language/crates/baml_compiler2_tir/src/generic_env.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs
  • baml_language/crates/baml_compiler2_tir/src/lib.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_tests/tests/interfaces_class_generics.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • baml_language/crates/baml_tests/tests/interfaces_class_generics.rs

Comment thread baml_language/crates/baml_compiler2_tir/src/generic_env.rs

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/sdks/csharp/sdkgen_csharp/src/semantic.rs (1)

797-808: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Preserve Ty::TypeVar identity in C# generic resolution.

The lookups resolve generated type variables by spelling alone while Ty::TypeVar also carries a ParamTy index. Namespaced generic code such as class Foo<T> { ... class Bar<T> { fn f() -> List<T> } } or receiver-method iter results can therefore resolve the inner T to the wrong local type token. Keep ParamTy/index identity through type_source_for and the render_ token/substitution paths, and add a Rust unit test with shadowed T parameters.

🤖 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/sdks/csharp/sdkgen_csharp/src/semantic.rs` around lines 797 -
808, Preserve the ParamTy/index identity when resolving Ty::TypeVar instead of
matching only by spelling, and carry that identity through type_source_for plus
the render_ token/substitution paths; update all affected sites in
baml_language/sdks/csharp/sdkgen_csharp/src/semantic.rs at lines 797-808,
2528-2545, 2868-2875, 3179-3192, and 3965-3976. Ensure shadowed generic
parameters and receiver-method iter results resolve to the correct C# type
token, and add a Rust unit test covering nested or shadowed T parameters.
🧹 Nitpick comments (3)
baml_language/crates/baml_compiler2_tir/src/interfaces.rs (1)

1240-1252: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Give test params distinct indices so index identity is actually exercised.

param() pins every parameter to index 0, so these tests only ever discriminate ParamTy by name — the exact dimension this PR introduces (index identity) is untested. Distinct indices would catch a regression where ParamTy equality/hashing drops or mis-uses the index.

♻️ Suggested helper
-    fn param(name: &str) -> ParamTy {
-        ParamTy::new(0, Name::new(name))
-    }
+    fn param_at(index: u32, name: &str) -> ParamTy {
+        ParamTy::new(index, Name::new(name))
+    }
+
+    fn param(name: &str) -> ParamTy {
+        // Stable per-name index so distinct params never share an index.
+        param_at(u32::from(name.as_bytes()[0]), name)
+    }

As per coding guidelines, "Prefer writing Rust unit tests over integration tests where possible" — these in-crate tests are the right place for that coverage.

🤖 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/baml_compiler2_tir/src/interfaces.rs` around lines 1240
- 1252, Update the test helper param and its call sites in the match_ty_pattern
tests so each parameter uses a distinct index instead of param() always
assigning index 0. Preserve the existing names and assertions while ensuring the
tests exercise ParamTy identity by both index and name.

Source: Coding guidelines

baml_language/crates/baml_compiler2_tir/src/builder/interface_resolution.rs (1)

1066-1077: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Derive method-generic ParamTys from the generic environment instead of minting fresh indices.

ParamTy identity matters for substitution and bindings, while GenericEnvData builds method defaults with ParamTy::new(next_index, name). Using interface_env.param_count() + offset here can produce different index/name pairs for the same method generic, and future interface-related ParamTy index changes would silently desynchronize this path. Use the shared helper/construction for all generic params instead.

🤖 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/baml_compiler2_tir/src/builder/interface_resolution.rs`
around lines 1066 - 1077, Update the method parameter construction in the
interface resolution path to derive each generic ParamTy from the method’s
GenericEnvData/shared generic-parameter helper rather than calculating indices
from interface_env.param_count() and offset. Ensure the resulting index/name
pairs exactly match the method defaults and remain synchronized with future
ParamTy index changes, while preserving the existing extra_generic_names
ordering.
baml_language/crates/baml_compiler2_mir/src/lower.rs (1)

3439-3452: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Synthesized Self slot index has no corresponding runtime frame slot.

When Self isn't already in enclosing_generic_params, this mints ParamTy::new(max+1, "Self"). That's fine for name resolution inside lower_type_expr, but the resulting Tir2Ty::TypeVar(self_param, …) now carries an index that would map to a non-existent TypeArgRef if it ever reaches template lowering. Today it only flows into convert_tir_ty_for_runtime; a comment pinning that invariant (or a sentinel index) would keep the next refactor from silently emitting a bogus slot.

🤖 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/baml_compiler2_mir/src/lower.rs` around lines 3439 -
3452, Document the invariant at the synthesized Self parameter in the fallback
branch of the generic-parameter lookup: its index is only for name resolution
and must never be treated as a runtime frame or TypeArgRef slot during template
lowering. Keep the existing index allocation and ensure the comment clearly
identifies convert_tir_ty_for_runtime as the boundary where this assumption
currently applies.
🤖 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_mir/src/lower.rs`:
- Around line 856-862: Update the Tir2Ty::TypeVar branch in tir2_to_template to
avoid asserting when the parameter is absent from generic_params. Return
TyTemplate::TypeArgRef(param.index()) for in-scope parameters and
TyTemplate::Wildcard for out-of-scope parameters, matching
tir2_to_dispatch_guard_template behavior.

In `@baml_language/crates/baml_compiler2_tir/src/builder.rs`:
- Around line 6757-6761: Update the function-type checking path around
surface_throws_ty so an omitted func_def.throws preserves contextual_throws
unchanged instead of using lambda_effective_throws. Keep the explicit throws_ty
branch intact, while allowing lambda_effective_throws to remain the body’s
effective boundary for inference.

In `@baml_language/crates/baml_type/src/normalize/tests.rs`:
- Around line 69-71: Update the test fixture’s type-variable bounds lookup in
type_var_bound to preserve the full ParamTy identity instead of reducing it to
param.name(). Change var_bounds and the typevar helper to use indexed ParamTy
keys, and construct explicit index/name pairs so same-named parameters with
different indices can be represented and tested.

In `@baml_language/sdks/rust/sdkgen_rust/src/lib.rs`:
- Around line 854-858: The typevar helper currently assigns every generic
variable to ParamTy slot 0, collapsing multi-parameter fixtures. Update typevar
and its call sites to accept and pass distinct slot indices, ensuring T and U
use separate ParamTy slots (for example, U uses 1), then run cargo test --lib
from the sdkgen_rust crate directory.

---

Outside diff comments:
In `@baml_language/sdks/csharp/sdkgen_csharp/src/semantic.rs`:
- Around line 797-808: Preserve the ParamTy/index identity when resolving
Ty::TypeVar instead of matching only by spelling, and carry that identity
through type_source_for plus the render_ token/substitution paths; update all
affected sites in baml_language/sdks/csharp/sdkgen_csharp/src/semantic.rs at
lines 797-808, 2528-2545, 2868-2875, 3179-3192, and 3965-3976. Ensure shadowed
generic parameters and receiver-method iter results resolve to the correct C#
type token, and add a Rust unit test covering nested or shadowed T parameters.

---

Nitpick comments:
In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 3439-3452: Document the invariant at the synthesized Self
parameter in the fallback branch of the generic-parameter lookup: its index is
only for name resolution and must never be treated as a runtime frame or
TypeArgRef slot during template lowering. Keep the existing index allocation and
ensure the comment clearly identifies convert_tir_ty_for_runtime as the boundary
where this assumption currently applies.

In `@baml_language/crates/baml_compiler2_tir/src/builder/interface_resolution.rs`:
- Around line 1066-1077: Update the method parameter construction in the
interface resolution path to derive each generic ParamTy from the method’s
GenericEnvData/shared generic-parameter helper rather than calculating indices
from interface_env.param_count() and offset. Ensure the resulting index/name
pairs exactly match the method defaults and remain synchronized with future
ParamTy index changes, while preserving the existing extra_generic_names
ordering.

In `@baml_language/crates/baml_compiler2_tir/src/interfaces.rs`:
- Around line 1240-1252: Update the test helper param and its call sites in the
match_ty_pattern tests so each parameter uses a distinct index instead of
param() always assigning index 0. Preserve the existing names and assertions
while ensuring the tests exercise ParamTy identity by both index and name.
🪄 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: cec392b5-7c67-46ce-a1d5-351695710130

📥 Commits

Reviewing files that changed from the base of the PR and between b4ef530 and 2dc7806.

⛔ Files ignored due to path filters (4)
  • baml_language/sdks/go/baml_go/internal/cffi/baml_type.pb.go is excluded by !**/*.pb.go
  • baml_language/sdks/go/bridge_go/cffi/proto/baml_bridge/cffi/v1/baml_type.pb.go is excluded by !**/*.pb.go
  • baml_language/sdks/typescript/bridge_typescript/dist/proto/baml_cffi.d.ts is excluded by !**/dist/**
  • baml_language/sdks/typescript/bridge_typescript/dist/proto/baml_cffi.js is excluded by !**/dist/**
📒 Files selected for processing (61)
  • baml_language/crates/baml_codegen_types/src/ty.rs
  • baml_language/crates/baml_compiler2_emit/src/lib.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_tir/src/builder/associated_projection.rs
  • baml_language/crates/baml_compiler2_tir/src/builder/interface_resolution.rs
  • baml_language/crates/baml_compiler2_tir/src/callable.rs
  • baml_language/crates/baml_compiler2_tir/src/exhaustiveness.rs
  • baml_language/crates/baml_compiler2_tir/src/generic_env.rs
  • baml_language/crates/baml_compiler2_tir/src/generics.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces/coherence.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs
  • baml_language/crates/baml_compiler2_tir/src/lib.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_compiler2_tir/src/package_interface.rs
  • baml_language/crates/baml_compiler2_tir/src/self_type.rs
  • baml_language/crates/baml_compiler2_tir/src/throw_inference.rs
  • baml_language/crates/baml_compiler2_tir/src/ty.rs
  • baml_language/crates/baml_compiler2_tir/src/type_context.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_lsp2_actions/src/type_info.rs
  • baml_language/crates/baml_project/src/client_codegen.rs
  • baml_language/crates/baml_type/src/family.rs
  • baml_language/crates/baml_type/src/lib.rs
  • baml_language/crates/baml_type/src/normalize.rs
  • baml_language/crates/baml_type/src/normalize/tests.rs
  • baml_language/crates/baml_type/src/param.rs
  • baml_language/crates/baml_type/src/realized_ty.rs
  • baml_language/crates/baml_type/src/runtime_ty.rs
  • baml_language/crates/baml_type/src/template.rs
  • baml_language/crates/baml_type_runtime/src/lib.rs
  • baml_language/crates/bex_engine/src/conversion.rs
  • baml_language/crates/bex_engine/src/trace_value_encode.rs
  • baml_language/crates/bex_vm/src/package_baml/resolve.rs
  • baml_language/crates/bex_vm/src/type_context.rs
  • baml_language/crates/bex_vm/src/type_match.rs
  • baml_language/crates/bex_vm_types/src/types/interface.rs
  • baml_language/crates/bridge_ctypes/src/ty_decode.rs
  • baml_language/crates/bridge_ctypes/src/ty_encode.rs
  • baml_language/crates/bridge_ctypes/types/baml_bridge/cffi/v1/baml_type.proto
  • baml_language/sdks/cpp/bridge_cpp/pb/baml_bridge/cffi/v1/baml_type.pb.cc
  • baml_language/sdks/cpp/bridge_cpp/pb/baml_bridge/cffi/v1/baml_type.pb.h
  • baml_language/sdks/csharp/sdkgen_csharp/src/semantic.rs
  • baml_language/sdks/go/sdkgen_go/src/lib.rs
  • baml_language/sdks/go/sdkgen_go/src/types.rs
  • baml_language/sdks/java/sdkgen_java/src/lib.rs
  • baml_language/sdks/java/sdkgen_java/src/translate_ty.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/lib.rs
  • baml_language/sdks/python/rust/sdkgen_python_pydantic2/src/translate_ty.rs
  • baml_language/sdks/python/src/baml_bridge/cffi/v1/baml_type_pb2.py
  • baml_language/sdks/python/src/baml_bridge/cffi/v1/baml_type_pb2.pyi
  • baml_language/sdks/rust/bridge_rust/src/wire/baml_bridge.cffi.v1.rs
  • baml_language/sdks/rust/sdkgen_rust/src/effect_rename.rs
  • baml_language/sdks/rust/sdkgen_rust/src/lib.rs
  • baml_language/sdks/swift/Sources/BamlBridge/Proto/.generated-from
  • baml_language/sdks/swift/Sources/BamlBridge/Proto/baml_type.pb.swift
  • baml_language/sdks/typescript/bridge_typescript/typescript_src/proto/baml_cffi.d.ts
  • baml_language/sdks/typescript/bridge_typescript/typescript_src/proto/baml_cffi.js
  • baml_language/sdks/typescript/sdkgen_typescript_shared/src/translate_ty.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • baml_language/crates/baml_compiler2_tir/src/inference.rs

Comment thread baml_language/crates/baml_compiler2_mir/src/lower.rs Outdated
Comment thread baml_language/crates/baml_compiler2_tir/src/builder.rs Outdated
Comment thread baml_language/crates/baml_type/src/normalize/tests.rs Outdated
Comment thread baml_language/sdks/rust/sdkgen_rust/src/lib.rs Outdated
@codeshaunted codeshaunted changed the title Refactor TIR generic environments and fix inherited bounds Use indexed generic parameter identities Jul 27, 2026
# Conflicts:
#	baml_language/crates/baml_compiler2_emit/src/lib.rs
#	baml_language/crates/baml_compiler2_mir/src/lower.rs
#	baml_language/crates/baml_compiler2_tir/src/builder.rs
#	baml_language/crates/baml_compiler2_tir/src/interfaces.rs
#	baml_language/crates/baml_compiler2_tir/src/interfaces/coherence.rs
#	baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
#	baml_language/crates/baml_type/src/template.rs

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/crates/baml_compiler2_tir/src/unify.rs (1)

84-120: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Traverse associated-type projections when detecting bound variables.

Ty::AssociatedTypeProjection falls through to false. Consequently, try_union_set_equality can treat a union containing <T as I>::Item as ground and return No against a concrete union, bypassing unify_into’s conservative projection-overlap rule. This can incorrectly classify overlapping impl subjects as disjoint.

Proposed fix
         Ty::Function {
             params,
             ret,
             throws,
             ..
         } => {
             params
                 .iter()
                 .any(|FunctionParamTy { ty, .. }| contains_bound_typevar(ty, generic_params))
                 || contains_bound_typevar(ret, generic_params)
                 || contains_bound_typevar(throws, generic_params)
         }
+        Ty::AssociatedTypeProjection {
+            base, interface, ..
+        } => {
+            contains_bound_typevar(base, generic_params)
+                || interface
+                    .tys()
+                    .any(|ty| contains_bound_typevar(ty, generic_params))
+        }
         _ => false,
🤖 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/baml_compiler2_tir/src/unify.rs` around lines 84 - 120,
Update contains_bound_typevar to explicitly traverse
Ty::AssociatedTypeProjection, checking its projected type and any
associated-type arguments or bindings for generic parameters using the same
recursive detection. Ensure projections containing a bound type variable return
true so try_union_set_equality does not classify them as ground before
unify_into applies its conservative overlap handling.
🤖 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.

Outside diff comments:
In `@baml_language/crates/baml_compiler2_tir/src/unify.rs`:
- Around line 84-120: Update contains_bound_typevar to explicitly traverse
Ty::AssociatedTypeProjection, checking its projected type and any
associated-type arguments or bindings for generic parameters using the same
recursive detection. Ensure projections containing a bound type variable return
true so try_union_set_equality does not classify them as ground before
unify_into applies its conservative overlap handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4803565c-df5b-4fdd-8c07-d21e2b44f867

📥 Commits

Reviewing files that changed from the base of the PR and between 2dc7806 and fa2ee45.

📒 Files selected for processing (14)
  • baml_language/crates/baml_compiler2_emit/src/lib.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_tir/src/builder/associated_projection.rs
  • baml_language/crates/baml_compiler2_tir/src/exhaustiveness.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces/coherence.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs
  • baml_language/crates/baml_compiler2_tir/src/lib.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_compiler2_tir/src/pattern_overlap.rs
  • baml_language/crates/baml_compiler2_tir/src/unify.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
🚧 Files skipped from review as they are similar to previous changes (11)
  • baml_language/crates/baml_compiler2_tir/src/exhaustiveness.rs
  • baml_language/crates/baml_compiler2_tir/src/lib.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_compiler2_tir/src/builder/associated_projection.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs
  • baml_language/crates/baml_compiler2_emit/src/lib.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/inference.rs

@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

🤖 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_type/src/param.rs`:
- Around line 81-85: The slot_by_name lookup incorrectly selects the first
matching parameter when flattened frames contain shadowed owner and method
generics. Resolve slots from the indexed ParamTy wherever available; otherwise
make name-based lookup shadowing-aware or reject ambiguous matches, preserving
the inner parameter’s slot. Add a regression test covering outer and inner
parameters with the same name and verifying the inner parameter resolves
correctly.
🪄 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: bc61caac-6f19-4e4a-81bc-da8bcd6a414f

📥 Commits

Reviewing files that changed from the base of the PR and between af8e97b and 8e68574.

📒 Files selected for processing (4)
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_tir/src/ty.rs
  • baml_language/crates/baml_type/src/param.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • baml_language/crates/baml_compiler2_tir/src/ty.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs

Comment thread baml_language/crates/baml_type/src/param.rs

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/crates/baml_type/src/param.rs (1)

34-41: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Guard the appended index range against u32 overflow.

first_index + offset is not validated as a sum. If the frame is near u32::MAX, release builds can wrap indices and create duplicate ParamTy identities. Validate the complete appended range before extending the frame.

Proposed fix
 pub fn extend_frame(frame: &mut Vec<Self>, names: &[Name]) {
     let first_index = u32::try_from(frame.len()).expect("generic parameter count fits in u32");
+    let count = u32::try_from(names.len()).expect("generic parameter count fits in u32");
+    first_index
+        .checked_add(count)
+        .expect("generic parameter index range fits in u32");
     frame.extend(names.iter().enumerate().map(|(offset, name)| {
         Self::new(
-            first_index + u32::try_from(offset).expect("generic parameter index fits in u32"),
+            first_index
+                .checked_add(u32::try_from(offset).expect("generic parameter index fits in u32"))
+                .expect("generic parameter index fits in u32"),
             name.clone(),
         )
     }));
 }
🤖 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/baml_type/src/param.rs` around lines 34 - 41, Update
ParamTy::extend_frame to validate that the entire appended range, from
frame.len() through frame.len() + names.len() - 1, fits within u32 before
calling frame.extend. Reject overflow explicitly, then preserve the existing
index generation for valid ranges.
🧹 Nitpick comments (1)
baml_language/crates/baml_type/src/param.rs (1)

102-110: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover direct indexed lookup in the shadowing regression test.

The test verifies slot_by_name, but not that slot(&outer) and slot(&inner) preserve distinct indexed identities. Add assertions for both direct lookups.

🤖 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/baml_type/src/param.rs` around lines 102 - 110, Extend
the test frame_index_distinguishes_same_named_parameters to assert that direct
layout lookups for both outer and inner parameters return their distinct indexed
slots via slot(&outer) and slot(&inner), while preserving the existing
slot_by_name shadowing assertion.
🤖 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.

Outside diff comments:
In `@baml_language/crates/baml_type/src/param.rs`:
- Around line 34-41: Update ParamTy::extend_frame to validate that the entire
appended range, from frame.len() through frame.len() + names.len() - 1, fits
within u32 before calling frame.extend. Reject overflow explicitly, then
preserve the existing index generation for valid ranges.

---

Nitpick comments:
In `@baml_language/crates/baml_type/src/param.rs`:
- Around line 102-110: Extend the test
frame_index_distinguishes_same_named_parameters to assert that direct layout
lookups for both outer and inner parameters return their distinct indexed slots
via slot(&outer) and slot(&inner), while preserving the existing slot_by_name
shadowing assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1af84eca-64c2-4893-bced-2d6d9679ad05

📥 Commits

Reviewing files that changed from the base of the PR and between 8e68574 and 4e6a74d.

📒 Files selected for processing (4)
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_type/src/param.rs
  • baml_language/crates/bex_vm/src/vm.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
baml_language/crates/baml_compiler2_mir/src/lower.rs (1)

694-698: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve canonical generic-parameter order instead of iterating FxHashMap keys.

Both helpers now derive ScopeCtx.generic_params from bindings.keys(). Hash-map iteration is not declaration/frame order, so nested parameters with the same name can resolve to the wrong ParamTy; consumers that build runtime templates from this slice can also receive incorrect slot ordering. Pass the owning scope’s canonical ordered &[ParamTy] instead of reconstructing it from the map, and add a nested-shadowing unit test.

Also applies to: 727-731

🤖 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/baml_compiler2_mir/src/lower.rs` around lines 694 - 698,
Update both helpers around the generic-parameter collection to accept and use
the owning scope’s canonical ordered &[ParamTy] instead of deriving order from
bindings.keys(). Preserve that slice when constructing ScopeCtx and when
generating runtime templates so nested shadowed parameters resolve to the
correct ParamTy and slot order; add a unit test covering nested
generic-parameter shadowing.
🤖 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.

Outside diff comments:
In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 694-698: Update both helpers around the generic-parameter
collection to accept and use the owning scope’s canonical ordered &[ParamTy]
instead of deriving order from bindings.keys(). Preserve that slice when
constructing ScopeCtx and when generating runtime templates so nested shadowed
parameters resolve to the correct ParamTy and slot order; add a unit test
covering nested generic-parameter shadowing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 0871a30d-970f-48ee-bc61-83c416494f00

📥 Commits

Reviewing files that changed from the base of the PR and between 8e68574 and 4e6a74d.

📒 Files selected for processing (4)
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_type/src/param.rs
  • baml_language/crates/bex_vm/src/vm.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • baml_language/crates/baml_type/src/param.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs

# Conflicts:
#	baml_language/crates/baml_compiler2_mir/src/lower.rs

@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

🤖 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_tests/baml_src/ns_interfaces_class_generics/interfaces_class_generics.baml`:
- Around line 109-111: Update the regression function aem_accept_echo to invoke
the passed AemEcho<int> value’s echo operation, exercising the alpha-equivalent
generic echo<A, B extends AemEq<A>> implementation and its bound instead of
returning a constant. Preserve the function’s int result contract.
🪄 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: 572b6689-b013-46cb-ab67-b0e426b33e59

📥 Commits

Reviewing files that changed from the base of the PR and between 4e6a74d and 28f8f8f.

⛔ Files ignored due to path filters (4)
  • baml_language/crates/baml_tests/snapshots/baml_src/interfaces_associated_types.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/interfaces_class_generics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/lambdas.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_5_mir.snap is excluded by !**/*.snap
📒 Files selected for processing (8)
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_tests/baml_src/ns_interfaces_associated_types/interfaces_associated_types.baml
  • baml_language/crates/baml_tests/baml_src/ns_interfaces_class_generics/interfaces_class_generics.baml
  • baml_language/crates/baml_tests/baml_src/ns_lambdas/lambdas.baml
  • baml_language/crates/baml_type/src/lib.rs
💤 Files with no reviewable changes (1)
  • baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • baml_language/crates/baml_type/src/lib.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs

@codeshaunted
codeshaunted enabled auto-merge July 27, 2026 23:43
@codeshaunted
codeshaunted added this pull request to the merge queue Jul 27, 2026
Merged via the queue into canary with commit 26dbf60 Jul 28, 2026
83 checks passed
@codeshaunted
codeshaunted deleted the avery/b-896 branch July 28, 2026 00:08
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