Skip to content

[codex] implement iterable for loops#3705

Merged
aaronvg merged 7 commits into
canaryfrom
codex/iterable-for-loops
Jun 8, 2026
Merged

[codex] implement iterable for loops#3705
aaronvg merged 7 commits into
canaryfrom
codex/iterable-for-loops

Conversation

@aaronvg

@aaronvg aaronvg commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add Iterable as the interface used to turn values into iterators, with arrays implementing it through ArrayIterator.
  • Lower for (let x in value) through Iterable.iter() and Iterator.next() instead of the previous array/index path.
  • Add array-first fluent iterator methods and coverage for direct array iteration over ints, classes, and union elements.

Why

BAML for in syntax should work like the Rust/JS iterable model: arrays and iterator adapters participate through the same interface machinery, so users do not need to write Iterator.new(...) or rely on compiler special cases.

Validation

  • cargo check -p bex_vm -p baml_compiler2_mir -p baml_compiler2_tir
  • INSTA_UPDATE=always cargo nextest run -p baml_tests __baml_std__
  • cargo nextest run -p baml_tests --test baml_src baml_test
  • INSTA_UPDATE=always cargo nextest run -p baml_tests --test baml_src bytecode
  • git diff --check
  • verified no stray .snap.new files

Note

Medium Risk
Touches core MIR lowering, interface dispatch, and bytecode branch emission; behavior changes for all for in loops and many interface method calls.

Overview
for in now goes through Iterable/Iterator instead of index-based array lowering. MIR calls iter() and next() until Done; non-iterable collections panic at runtime. TIR infers loop variables from Iterable.Item and folds Iterable.Error into throw analysis.

Stdlib: Array gains fluent helpers (for_each, filter, filter_map, step_by, chain, peekable, collect, count) built on ArrayIterator. Iterator adds for_each; chain accepts any Iterable and unions error types via a third generic on Chain.

Compiler fixes supporting dispatch: Interface lowering/dispatch is expanded—tir_type_satisfies_dispatch_request, registry lookup across packages, iterable for lowering, associated-type frame args for interface defaults, Iterable params on function signatures, and explicit Object type args. Bytecode emission no longer skips branch conditions when the else block is unreachable (regression test added). Closure/map snapshots pick up extra load_type for element type args.

Reviewed by Cursor Bugbot for commit eb8e1e0. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added fluent iterator/array methods: for_each, filter, filter_map, step_by, chain, peekable, collect, and count.
    • Iterator API: new for_each terminal; chain accepts any iterable and combines iterator error types.
    • for...in loops now use the Iterable interface so more collection types iterate naturally and iterator-associated errors are included.
  • Tests

    • Added extensive tests covering iterators, fluent adapters, peekable behavior, and for-in scenarios.

@vercel

vercel Bot commented Jun 6, 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 Jun 8, 2026 5:21am
promptfiddle Ready Ready Preview, Comment Jun 8, 2026 5:21am
promptfiddle2 Ready Ready Preview, Comment Jun 8, 2026 5:21am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4cea7f48-ad9d-4c81-bc56-dc39dba91dc1

📥 Commits

Reviewing files that changed from the base of the PR and between 058e992 and eb8e1e0.

⛔ Files ignored due to path filters (1)
  • baml_language/crates/baml_tests/snapshots/baml_src/iter.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • baml_language/crates/baml_compiler2_emit/src/emit.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml
  • baml_language/crates/baml_tests/src/compiler2_mir/mod.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • baml_language/crates/baml_compiler2_emit/src/emit.rs
  • baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml

📝 Walkthrough

Walkthrough

Adds Array adapter methods and Iterator.for_each; generalizes Chain error typing; implements Iterable-based for-loop type inference and MIR lowering; refactors interface dispatch/blanket-impl resolution; refines runtime template matching; and adds iterator tests.

Changes

Iterable-based Iterator Methods and For Loop Support

Layer / File(s) Summary
Iterator interface contract and Array adapter methods
baml_language/crates/baml_builtins2/baml_std/baml/containers.baml, baml_language/crates/baml_builtins2/baml_std/baml/ns_iter/iter.baml
Iterator gains for_each; chain accepts Iterable and returns an iterator whose Error is the union of both sides; Chain generalized to two error params. Array<T> adds for_each, filter, filter_map, step_by, chain, peekable, collect, count delegating to baml.iter adapters.
Type inference for Iterable interface
baml_language/crates/baml_compiler2_tir/src/builder.rs
Adds helpers to construct baml.iter qualified names, view a type through Iterable, and extract Item/Error associated bindings. Stmt::For element inference now uses Iterable.Item and includes Iterable.Error in throws collection.
For loop lowering via Iterable interface & dispatch rewrites
baml_language/crates/baml_compiler2_mir/src/lower.rs
Replaces index-based for desugaring with Iterable-based lowering that calls iter() and next(), checks for Done, binds Item to the loop pattern, preserves watch/unwatch and loop control wiring, and implements broad refactors for interface-default/blanket-impl resolution and registry scanning across package deps.
Runtime type template matching refinements
baml_language/crates/bex_vm/src/vm.rs
guard_template_matches uses subtype checks for known frame type-arg refs and tightens union-template matching to require coverage of all actual union parts when actual is a union.
Emit/analysis adjustments
baml_language/crates/baml_compiler2_emit/src/analysis.rs, baml_language/crates/baml_compiler2_emit/src/emit.rs
Removed is_block_unreachable; Terminator::Branch emission now always evaluates the condition and emits PopJumpIfFalse; adds unit test asserting the emitted condition-check sequence.
Test coverage for iterator functionality & runtime-dispatch tests
baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml, baml_language/crates/baml_tests/tests/interfaces_associated_types.rs, baml_language/crates/baml_tests/src/compiler2_mir/mod.rs
Adds IterLoopBox and extensive tests covering for-in iteration and adapter pipelines (for_each, collect/count, filter.step_by.collect, filter_map.collect, chain.collect, peekable, Repeat), plus test harness helper and two tokio tests for partially-open associated-type dispatch and a MIR snapshot test for shadowed local dispatch.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • BoundaryML/baml#3702: Related iterator stdlib changes; evolves baml.iter interfaces and implementations.
  • BoundaryML/baml#3425: Overlaps with loop watch/unwatch teardown and loop-related control-flow refactors.

Poem

🐰 I hop through arrays with a thoughtful cheer,
New adapters let each element steer,
For-loops call iter and gently bind,
Types and lowering dance, neatly aligned,
A rabbit nods—compiler craft sincere.

🚥 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 '[codex] implement iterable for loops' directly and clearly describes the main objective of the PR: implementing iterable support for for-loops. It accurately reflects the primary architectural change across the changeset.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 codex/iterable-for-loops

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 and usage tips.

@github-actions

github-actions Bot commented Jun 6, 2026

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.

Comment thread baml_language/crates/baml_compiler2_tir/src/builder.rs
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

No description provided.

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

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)

6003-6018: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Run the formatter on this file before merging.

CI's pre-commit step is already rewriting these hunks, so this file will keep the pipeline red until the generated formatting diff is committed.

Also applies to: 9054-9084, 9146-9158, 9246-9285

🤖 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 6003 -
6018, Formatting is inconsistent in the receiver_class_type_arg_operands block
(and other hunks listed) causing CI pre-commit to rewrite the file; run the Rust
formatter (rustfmt) or your repository's pre-commit formatter on
baml_language/crates/baml_compiler2_mir/src/lower.rs and commit the resulting
changes so the code around receiver_class_type_arg_operands,
enclosing_generic_params, ty_to_template, builder.temp, Place::local and
Rvalue::LoadType matches the project's style; ensure the same formatting is
applied to the other affected ranges (around lines mentioned in the review)
before pushing.

Source: Pipeline failures

🧹 Nitpick comments (2)
baml_language/crates/bex_vm/src/vm.rs (1)

47-50: ⚡ Quick win

Add unit coverage for the new subtype and union guard semantics.

These branches now define IsType behavior for templated runtime checks, but the file-local #[cfg(test)] module still doesn't exercise the two new edge cases: accepting subtype matches through TypeArgRefOrWildcard, and rejecting actual unions with an uncovered member. Please add focused unit tests here and run cargo test --lib locally before merge.

As per coding guidelines, "Prefer writing Rust unit tests over integration tests where possible" and "Always run cargo test --lib if you changed any Rust code".

Also applies to: 79-88

🤖 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/vm.rs` around lines 47 - 50, Add two focused
unit tests inside the file-local #[cfg(test)] module in vm.rs to cover the new
templated runtime check branches: (1) a test that constructs a frame_type_args
entry and uses TyTemplate::TypeArgRefOrWildcard(n) to verify an actual type that
is a subtype of the referenced expected type is accepted (exercise the
actual.is_subtype_of(expected) path), and (2) a test that builds an actual union
type containing a member not covered by the union guard to verify it is rejected
(exercise the union guard rejection path referenced around the same code and
lines 79-88). Locate the checks via TyTemplate::TypeArgRefOrWildcard,
frame_type_args, and Ty::BuiltinUnknown, assert the expected boolean result from
the IsType/runtime check, and run cargo test --lib to verify both tests pass.

Source: Coding guidelines

baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml (1)

59-62: ⚡ Quick win

Add one failure-path test for non-iterable for-in inputs.

These tests cover iterable success paths well, but they currently miss the contract where for (let x in value) should panic if value is not iterable. Adding one negative test here would harden regressions in lowering/type-dispatch changes.

Suggested test addition
+test "iter_for_in_non_iterable_panics" {
+  // Adjust to the project's panic/assertion primitive for runtime failures.
+  assert.throws(() -> void {
+    let out: int[] = [];
+    for (let x in 123) {
+      out.push(x);
+    }
+  })
+}
🤖 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/baml_src/ns_iter/iter.baml` around lines 59 -
62, Add a negative test alongside iter_for_in_range that verifies a for-in loop
panics on non-iterable input: create a new test named like
"iter_for_in_non_iterable" in the same file
(baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml) which calls the
same lowering/iteration routine (mirror how iter_for_in_range() is used) but
passes a non-iterable value (e.g., a number or null) and asserts that the call
throws/panics; ensure the assertion uses the project test helper for expecting
failures (parallel to how successful cases use baml.deep_equals) so regressions
in the for (let x in value) non-iterable path are caught.
🤖 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 8941-8945: The early-return that treats any requested_ty with
contains_assoc_projection(...) or Tir2Ty::TypeVar as unconstrained should be
removed; instead, in the logic around the match that currently returns true,
perform a structural walk/match of requested_ty (including nested nodes like
Map<Self.Item, int>) and attempt to match/substitute associated projections at
their concrete positions rather than short-circuiting the whole type; update the
handling in the same function where requested_ty is inspected so that
contains_assoc_projection(...) only triggers per-node projection processing
(recursing into Map, Tuple, Path, etc.) and do not treat a partially-open
associated type as a full wildcard that bypasses assoc matching or request
rewriting (also apply the same structural fix to the similar block around lines
handling the other occurrence noted in the review).
- Around line 1569-1618: The interface lookup in interface_view_from_registry
builds a packages list that omits dependency packages so implementations in
dependencies are missed; update interface_view_from_registry to expand the
package set the same way registry_dispatch_target_for_concrete does (include
dependency packages for the current file package and the target package) before
iterating registries—i.e., replace the current packages collection logic with
the dependency-expanded lookup used by registry_dispatch_target_for_concrete (or
call that helper) so PackageId::new /
baml_compiler2_tir::interfaces::package_implements_registry is consulted for all
dependency packages as well.

In `@baml_language/crates/baml_compiler2_tir/src/builder.rs`:
- Around line 5427-5430: Run the formatter (rustfmt / project pre-commit
formatter) to fix the formatting of the diagnostic call: reformat the
self.context.report_simple(...) invocation that reports
TirTypeError::NotIterable { ty: coll_ty } with *collection so it matches the
project's style (proper line breaks, indentation and trailing commas) — locate
the call to self.context.report_simple and the TirTypeError::NotIterable
construct in builder.rs and re-run the formatter so CI/pre-commit hooks no
longer rewrite this block.

---

Outside diff comments:
In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 6003-6018: Formatting is inconsistent in the
receiver_class_type_arg_operands block (and other hunks listed) causing CI
pre-commit to rewrite the file; run the Rust formatter (rustfmt) or your
repository's pre-commit formatter on
baml_language/crates/baml_compiler2_mir/src/lower.rs and commit the resulting
changes so the code around receiver_class_type_arg_operands,
enclosing_generic_params, ty_to_template, builder.temp, Place::local and
Rvalue::LoadType matches the project's style; ensure the same formatting is
applied to the other affected ranges (around lines mentioned in the review)
before pushing.

---

Nitpick comments:
In `@baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml`:
- Around line 59-62: Add a negative test alongside iter_for_in_range that
verifies a for-in loop panics on non-iterable input: create a new test named
like "iter_for_in_non_iterable" in the same file
(baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml) which calls the
same lowering/iteration routine (mirror how iter_for_in_range() is used) but
passes a non-iterable value (e.g., a number or null) and asserts that the call
throws/panics; ensure the assertion uses the project test helper for expecting
failures (parallel to how successful cases use baml.deep_equals) so regressions
in the for (let x in value) non-iterable path are caught.

In `@baml_language/crates/bex_vm/src/vm.rs`:
- Around line 47-50: Add two focused unit tests inside the file-local
#[cfg(test)] module in vm.rs to cover the new templated runtime check branches:
(1) a test that constructs a frame_type_args entry and uses
TyTemplate::TypeArgRefOrWildcard(n) to verify an actual type that is a subtype
of the referenced expected type is accepted (exercise the
actual.is_subtype_of(expected) path), and (2) a test that builds an actual union
type containing a member not covered by the union guard to verify it is rejected
(exercise the union guard rejection path referenced around the same code and
lines 79-88). Locate the checks via TyTemplate::TypeArgRefOrWildcard,
frame_type_args, and Ty::BuiltinUnknown, assert the expected boolean result from
the IsType/runtime check, and run cargo test --lib to verify both tests pass.
🪄 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

Run ID: fbb3cd82-a8d3-4840-a85b-3a735056afd8

📥 Commits

Reviewing files that changed from the base of the PR and between f485a76 and 0b16e75.

⛔ Files ignored due to path filters (20)
  • baml_language/crates/baml_tests/snapshots/baml_src/closures.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/for_loops.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/fs.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/glob.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/inferred_generic_type_args.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/iter.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/iter_impl_generics_only.core.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/iter_impl_generics_only.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/json_auto_derive.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/baml_src/lexical_scoping.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/maps.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/patterns_new_runtime.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/type_error_repro.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/typed_inputs.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/watch.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____03_hir.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
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____06_codegen.snap is excluded by !**/*.snap
📒 Files selected for processing (6)
  • baml_language/crates/baml_builtins2/baml_std/baml/containers.baml
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_iter/iter.baml
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml
  • baml_language/crates/bex_vm/src/vm.rs

Comment thread baml_language/crates/baml_compiler2_mir/src/lower.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_compiler2_mir/src/lower.rs
Comment thread baml_language/crates/baml_compiler2_mir/src/lower.rs
Comment thread baml_language/crates/baml_compiler2_mir/src/lower.rs

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 094e684. Configure here.

Comment thread 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.

🧹 Nitpick comments (1)
baml_language/crates/baml_tests/tests/interfaces_associated_types.rs (1)

130-160: 💤 Low value

Well-structured helper for multi-file runtime tests.

The helper correctly compiles multiple BAML files, locates the entry function by name suffix, constructs a BexEngine with native ops, and executes the function with no arguments. The Arc wrapping is necessary since call_function_bound_args requires &Arc<Self>.

Optional: improve error message clarity
         BexEngine::new(
             program,
             Arc::new(sys_ops::SysOps::native()),
             None,
             Vec::new(),
         )
-        .expect("engine")
+        .expect("BexEngine::new should succeed for compiled multi-file program")
🤖 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_associated_types.rs` around
lines 130 - 160, The panic when no function is found in run_multi_file_no_args
is terse; update the unwrap_or_else used to select entry to include the
requested entry_suffix and a short listing of available function names (from
program.function_indices.keys()) to aid debugging so the panic message reads
something like "function ending with `{entry_suffix}` not found; available
functions: ..."; locate the selection/unwrap in run_multi_file_no_args and
replace the panic with a formatted message that joins the keys into a string.
🤖 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_tests/tests/interfaces_associated_types.rs`:
- Around line 130-160: The panic when no function is found in
run_multi_file_no_args is terse; update the unwrap_or_else used to select entry
to include the requested entry_suffix and a short listing of available function
names (from program.function_indices.keys()) to aid debugging so the panic
message reads something like "function ending with `{entry_suffix}` not found;
available functions: ..."; locate the selection/unwrap in run_multi_file_no_args
and replace the panic with a formatted message that joins the keys into a
string.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 2be4a73c-45e4-4a65-ae2a-b5f89346c25a

📥 Commits

Reviewing files that changed from the base of the PR and between 9fc7bda and 094e684.

📒 Files selected for processing (2)
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_tests/tests/interfaces_associated_types.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • 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

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)

8408-8420: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Unify default-method owner-frame seeding.

These paths don't agree on where a default method's owner interface args live. Class-backed defaults are emitted with Static(Vec::new()), type-backed defaults return current_iface_args, and emit_method_candidate_switch() prepends owner_ops only when the ItemRef matches the originally requested interface. That means same-interface type implementor defaults get interface args twice, while defaults inherited from a requires parent get no provider associated-type frame args at all. In both cases the default body's enclosing_generic_params() layout is violated and generic/associated-type reads resolve incorrectly at runtime. Carry the provider interface view on the candidate and build the owner frame exactly once from that view. Please add unit coverage for both a same-interface primitive default and a required-interface inherited default.

As per coding guidelines, **/*.rs: Prefer writing Rust unit tests over integration tests where possible.

Also applies to: 8530-8559, 9053-9067, 9874-9884

🤖 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 8408 -
8420, The code is seeding default-method owner frames inconsistently: when
building InterfaceMethodCandidate in resolve_type_implementor_method you must
carry the provider-interface view (the interface/type whose generic/associated
params the default body uses) on the candidate instead of sometimes using
CalleeFrameSeed::Static(Vec::new()) or current_iface_args; update
InterfaceMethodCandidate to include a provider_iface_args (or reuse an existing
field) and set it on all paths (class-backed and type-backed defaults and
inherited requires), then modify emit_method_candidate_switch to build the owner
frame once from that provider view (prepend owner_ops exactly once when ItemRef
equals the originally requested interface using the new provider info) so
enclosing_generic_params() and associated-type reads resolve consistently; add
unit tests covering a same-interface primitive default and a required-interface
inherited default to assert correct generic/associated-type layout at runtime.

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.

Inline comments:
In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 3306-3361: source_param_interface_view_for_name/current fast-path
uses only param.name and can incorrectly match a shadowed local or closure arg;
change the shortcut to first resolve the binding at the expression site and only
return the enclosing function-parameter's interface view when that resolved
binding is the same parameter binding from the function signature. Concretely,
inside source_param_interface_view_for_expr and
source_param_interface_view_for_name use the existing resolver/lookup used
elsewhere in this crate to map the Path/Name at expr_id to its Binding/VarId,
check that the binding corresponds to the function parameter (not a
local/closure shadow), and only then compute the param type and call
interface_dispatch_target_for_tir_ty; add a unit test that declares a function
parameter shadowed by a local or closure (e.g. fn f(x: T){ let x = ...;
x.method() } ) to assert the method resolves to the inner type, not the outer
parameter.

---

Outside diff comments:
In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 8408-8420: The code is seeding default-method owner frames
inconsistently: when building InterfaceMethodCandidate in
resolve_type_implementor_method you must carry the provider-interface view (the
interface/type whose generic/associated params the default body uses) on the
candidate instead of sometimes using CalleeFrameSeed::Static(Vec::new()) or
current_iface_args; update InterfaceMethodCandidate to include a
provider_iface_args (or reuse an existing field) and set it on all paths
(class-backed and type-backed defaults and inherited requires), then modify
emit_method_candidate_switch to build the owner frame once from that provider
view (prepend owner_ops exactly once when ItemRef equals the originally
requested interface using the new provider info) so enclosing_generic_params()
and associated-type reads resolve consistently; add unit tests covering a
same-interface primitive default and a required-interface inherited default to
assert correct generic/associated-type layout at runtime.
🪄 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

Run ID: f5c52657-c3bd-4034-90ea-ab6acaab52cd

📥 Commits

Reviewing files that changed from the base of the PR and between 094e684 and 058e992.

⛔ Files ignored due to path filters (21)
  • baml_language/crates/baml_tests/snapshots/baml_src/for_loops.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/inferred_generic_type_args.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/iter.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/iter_impl_generics_only.core.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/iter_impl_generics_only.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/baml_src/lexical_scoping.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/patterns_new_runtime.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/typed_inputs.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/watch.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
  • baml_language/crates/baml_tests/snapshots/compiles/__baml_std__/baml_tests__compiles____baml_std____06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__testing_std__/baml_tests__compiles____testing_std____06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/closure_loop_variable/baml_tests__compiles__closure_loop_variable__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/lambda_advanced/baml_tests__compiles__lambda_advanced__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/lexical_scoping/baml_tests__compiles__lexical_scoping__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/parser_statements/baml_tests__compiles__parser_statements__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/patterns_new/baml_tests__compiles__patterns_new__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_expanded_unoptimized.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/tests/bytecode_format/snapshots/bytecode_format__bytecode_display_textual.snap is excluded by !**/*.snap
📒 Files selected for processing (4)
  • baml_language/crates/baml_compiler2_emit/src/analysis.rs
  • baml_language/crates/baml_compiler2_emit/src/emit.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml
💤 Files with no reviewable changes (1)
  • baml_language/crates/baml_compiler2_emit/src/analysis.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • baml_language/crates/baml_tests/baml_src/ns_iter/iter.baml

Comment thread baml_language/crates/baml_compiler2_mir/src/lower.rs
@aaronvg
aaronvg added this pull request to the merge queue Jun 8, 2026
Merged via the queue into canary with commit 0a91ec3 Jun 8, 2026
52 checks passed
@aaronvg
aaronvg deleted the codex/iterable-for-loops branch June 8, 2026 05:24
antoniosarosi added a commit that referenced this pull request Jun 8, 2026
Canary advanced 2 commits after round 4: 0a91ec3 [codex] iterable
for loops (#3705) and 4a866e7 (windows lld build chore). The
compiler source (builder.rs, lower.rs, emit.rs, analysis.rs) and
vm.rs auto-merged cleanly against #3705 — only 4 generated snapshots
conflicted; took canary's and regenerated to fold in our changes.

Also fixes a class of flaky timing assertions exposed by cold-build
runs. Three tests timed wall-clock around a call that COMPILES the
(growing) BAML stdlib before running — so a cold/large compile blew
past their promptness bounds, which actually guard against multi-second
cancellation HANGS, not compile time:

  - task_group::task_group_cancel_cancels_members
  - cancel_cascade::cancel_unblocks_await_on_non_descendant
  - spawn_semantics::parent_throw_cancels_running_children

Fix: compile OUTSIDE the timed region and measure only the engine run.
Added a public `run_compiled(program, entry, args, show_auto_derive)`
to the baml_tests engine harness (split out of run_test_with_options)
and a `build_engine`/`run_engine` split in the bex_engine task_group
test, so the assertions time execution alone. Bounds restored to tight
values (2s) well under the sleeps they guard.

Verified: cargo test --workspace --all-features (sdk_test_* excluded as
in CI) — all suites green, including the three above and baml_src on a
warm build; prek run --all-files clean. rustc 1.93.0.
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