Skip to content

Interface fixes and comparison operators - #3788

Merged
2kai2kai2 merged 20 commits into
canaryfrom
kai/comparison
Jun 17, 2026
Merged

2kai2kai2 merged 20 commits into
canaryfrom
kai/comparison

Conversation

@2kai2kai2

@2kai2kai2 2kai2kai2 commented Jun 17, 2026 •

Copy link
Copy Markdown
Contributor
  • baml.ops.Equals interface + baml.ops.equals_equals driver for ==
  • baml.ops.Compare interface directly corresponds to </>/<=/>=
  • Enforcement of orphan rule
  • Enforcement of interface coherence
  • Typearg-aware implements rule registry
  • Interface method virtual calls: if we cannot statically determine a call's exact implements rule (and thus concrete method implementation) at compile time, then we do a virtual method call. This is implemented as a new VM instruction, instead of the previous strategy which (unsoundly) did a switch over the receiver's type tag.
  • Bugfix: class inherent methods cannot satisfy interface method requirements
  • Many other minor bugfixes and improvements

Summary by CodeRabbit

  • New Features

    • Added Equals/Compare primitives (==, !=, and ordering) with structural equality for arrays/maps and a runtime fallback for dynamic operands.
    • Enabled open-world interface method dispatch for runtime-resolved interface calls.
    • Added package-scoped interface coherence checks with orphan-rule enforcement.
  • Bug Fixes

    • Tightened comparison semantics across types, rejecting invalid cross-type ordering and aligning equality behavior.
    • Corrected float NaN comparison behavior: all ordering and equality with NaN behaves as expected.
    • Updated invalid-operator diagnostics to consistently report operator symbols.

2kai2kai2 added 19 commits June 16, 2026 19:32
Along with implementations for primitives+builtin containers. This
commit this does not do any operator overloading, they are simply
interfaces.
Adds `type_implements_with_deps` in the TIR that allows us to search if
a given type implements a given interface in dependencies, not just the
current package.
This is what powers `==` and it works for *any* types, not just ones
that implement `baml.ops.Equals`. It is basically `deep_equals` except
it delegates to `baml.ops.Equals` whenever it reaches a value that
implements it.
The previous one only looked up by `TypeName` so did not work correctly
for blanket implementations.
Following Rust's RFC 2451 per BEP-044
The previous interface implementation did not check for overlapping
implements blocks across files. We now do a full cross-package coherece
check including blanket implementations to ensure there can never be
more than one implementation of a realized interface for a realized
concrete type.
While we don't really have user package dependencies, we should use the
full dependency tree for resolving interfaces rather than just direct
dependencies.
Since BAML has unions, checking for overlap between to `implements`
blocks is much harder than in Rust. In fact, it's an [NP-hard
problem](https://arxiv.org/abs/1611.05672) in the general case.

We now have a far more comprehensive overlap checker which should allow
a better analysis given BAML's union-equivalence rules. It will first
try a number of common/trivial fast-path cases, as well as reducing the
total search space. Then it will fall back to the general-case solver
which will only be run if the search space is within an acceptable upper
bound.
There will never be overlap between the interface-existentials
`Foo<Item=string>` and `Foo<Item=int>` because each concrete type may
only implement one. This change only increases permissiveness and does
not affect soundness.
- Recursion limit on coherence checker
- Docs
- Better diagnostics
`==` is now syntax sugar for the function, though some primitives will
emit builtin bytecode for a fast-path comparison.
If the types of each operand are provably disjoint (will never be equal)
then we emit a warning.
Adds the `VirtualCall` VM instruction which, given a `Self` receiver, an
iterface, a method name, and method arguments, will dispatch a call to
the correct concrete implementation.
@vercel

vercel Bot commented Jun 17, 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 17, 2026 9:14pm
promptfiddle Ready Ready Preview, Comment Jun 17, 2026 9:14pm
promptfiddle2 Ready Ready Preview, Comment Jun 17, 2026 9:14pm

Request Review

@2kai2kai2
2kai2kai2 enabled auto-merge June 17, 2026 18:36
@coderabbitai

coderabbitai Bot commented Jun 17, 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

Run ID: 25cacfae-22c1-441f-a5a4-1440ce75f07f

📥 Commits

Reviewing files that changed from the base of the PR and between be4fb65 and 19161cf.

⛔ Files ignored due to path filters (20)
  • baml_language/crates/baml_tests/snapshots/baml_src/floats.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/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
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/format_checks/baml_tests__diagnostic_errors__format_checks__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/format_checks/baml_tests__diagnostic_errors__format_checks__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__01_lexer__numeric_invariance.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__10_formatter__numeric_invariance.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/simple_type_error/baml_tests__diagnostic_errors__simple_type_error__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/simple_type_error/baml_tests__diagnostic_errors__simple_type_error__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_name_type_error/baml_tests__diagnostic_errors__test_expr_name_type_error__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_name_type_error/baml_tests__diagnostic_errors__test_expr_name_type_error__05_diagnostics.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
📒 Files selected for processing (21)
  • baml_language/crates/baml_builtins2_codegen/src/codegen.rs
  • baml_language/crates/baml_builtins2_codegen/src/extract.rs
  • baml_language/crates/baml_compiler2_ast/src/ast.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/infer_context.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/invalid_assignment/compound_ops.baml
  • baml_language/crates/baml_tests/baml_src/ns_floats/floats.baml
  • baml_language/crates/baml_tests/projects/diagnostic_errors/numeric_invariance/numeric_invariance.baml
  • baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs
  • baml_language/crates/baml_tests/tests/interfaces.rs
  • baml_language/crates/baml_tests/tests/interfaces_associated_types.rs
  • baml_language/crates/bex_vm/src/package_baml/json.rs
  • baml_language/crates/bex_vm/src/package_baml/type_class.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/bex_vm/tests/comparison_driver.rs
  • baml_language/crates/bex_vm/tests/projection_dest_calls.rs
  • baml_language/crates/bex_vm_types/src/bytecode.rs
🚧 Files skipped from review as they are similar to previous changes (18)
  • baml_language/crates/baml_tests/projects/diagnostic_errors/numeric_invariance/numeric_invariance.baml
  • baml_language/crates/baml_compiler2_tir/src/infer_context.rs
  • baml_language/crates/baml_lsp2_actions_tests/test_files/syntax/invalid_assignment/compound_ops.baml
  • baml_language/crates/baml_compiler2_ast/src/ast.rs
  • baml_language/crates/baml_builtins2_codegen/src/extract.rs
  • baml_language/crates/baml_builtins2_codegen/src/codegen.rs
  • baml_language/crates/baml_tests/baml_src/ns_floats/floats.baml
  • baml_language/crates/baml_compiler2_emit/src/lib.rs
  • baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs
  • baml_language/crates/bex_vm_types/src/bytecode.rs
  • baml_language/crates/bex_vm/src/package_baml/type_class.rs
  • baml_language/crates/bex_vm/tests/comparison_driver.rs
  • baml_language/crates/bex_vm/src/vm.rs
  • baml_language/crates/baml_tests/tests/interfaces_associated_types.rs
  • baml_language/crates/baml_compiler2_tir/src/builder.rs
  • baml_language/crates/baml_compiler2_tir/src/interfaces.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_tests/tests/interfaces.rs

📝 Walkthrough

Walkthrough

Adds comparison primitives, virtual interface dispatch, runtime registry wiring, type inference changes, and interface coherence validation.

Changes

Comparison, dispatch, and coherence

Layer / File(s) Summary
Type algebra foundations and impl-subject classification
baml_language/crates/baml_type/src/...
Adds Interface<T>, Ty::is_valid_impl_subject, and the baml_type::normalize API with canonicalization, subtype/equivalence, and constant-comparison reasoning plus unit tests.
Comparison stdlib and builtin codegen extraction
baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/comparison.baml, baml_language/crates/baml_builtins2/src/lib.rs, baml_language/crates/baml_builtins2_codegen/src/...
Adds Equals/Compare, registers the builtin file, extracts implements for blocks, and updates builtin codegen sanitization and owned-container handling.
TIR comparison inference and operator diagnostics
baml_language/crates/baml_compiler2_tir/src/..., baml_language/crates/baml_compiler2_ast/src/ast.rs
Reworks ==/!=/ordering inference around normalization and Compare, adds new type errors, and formats unary operators by symbol.
Package coherence, orphan rule, and interface diagnostics
baml_language/crates/baml_compiler2_tir/src/interfaces.rs, baml_language/crates/baml_compiler2_hir/src/package.rs, baml_language/crates/baml_compiler_diagnostics/src/diagnostic.rs, baml_language/crates/baml_lsp2_actions/src/check.rs
Adds package dependency closure, overlap diagnostics, orphan-rule checks, source spans, and LSP diagnostic wiring.
VirtualCall MIR/emit/bytecode plumbing
baml_language/crates/baml_compiler2_mir/src/..., baml_language/crates/baml_compiler2_emit/src/..., baml_language/crates/bex_vm_types/src/bytecode.rs
Adds VirtualCall to MIR, emit, optimization, pretty-printing, analysis, stack handling, and compact bytecode encoding.
Runtime interface registry and VM dispatch runtime
baml_language/crates/bex_vm_types/src/types.rs, baml_language/crates/bex_vm_types/src/errors.rs, baml_language/crates/baml_compiler2_emit/src/lib.rs, baml_language/crates/bex_vm/src/..., baml_language/crates/bex_engine/src/lib.rs
Replaces the interface registry model, builds runtime impl rules, dispatches VirtualCall, and resolves interface methods plus structural equality at runtime.
Comparison, coherence, and dispatch test updates
baml_language/crates/bex_vm/tests/..., baml_language/crates/baml_tests/...
Updates VM, compiler, and BAML tests for equality, ordering, interface dispatch, orphan rules, overlap diagnostics, and numeric invariance.

Node.js protobuf encodeDelimited fix

Layer / File(s) Summary
Fork-aware encodeDelimited generation
baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js
encodeDelimited now forks the writer when writer && writer.len is truthy.

Sequence Diagram(s)

sequenceDiagram
  participant BexVm
  participant resolve_implements_rule
  participant realize_frame
  participant execute_call_from_locals_offset
  BexVm->>resolve_implements_rule: concrete_ty, iface, iface_args
  resolve_implements_rule-->>BexVm: RuntimeImplRule + bound_args
  BexVm->>realize_frame: method.frame, bound_args
  realize_frame-->>BexVm: realized type_args
  BexVm->>execute_call_from_locals_offset: callee FQN, type_args
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~150 minutes

Possibly related PRs

  • BoundaryML/baml#3628: This PR also changes float comparison semantics and the tests that exercise ==/!= behavior.
  • BoundaryML/baml#3638: This PR also changes the compiler interface-dispatch lowering pipeline in baml_compiler2_mir/src/lower.rs.
  • BoundaryML/baml#3705: This PR also touches the same interface-dispatch machinery in baml_compiler2_mir/src/lower.rs.

Poem

🐇 Hop hop, the equals dance begins!
Two values meet — are they kin?
VirtualCall leaps through runtime space,
EqualsDriver locks each pair in place.
NaN? Not equal — IEEE says so!
Coherence guards the impl flow,
And rabbits cheer as == takes hold! 🎉

🚥 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 'Interface fixes and comparison operators' directly reflects the main changes: it introduces comparison operator interfaces and fixes interface-related issues in the compiler infrastructure.
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 kai/comparison

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.

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 17, 2026 18:37 Inactive
@github-actions

github-actions Bot commented Jun 17, 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.

@github-actions

Copy link
Copy Markdown

No description provided.

@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 17, 2026 18:49 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps June 17, 2026 18:56 Inactive

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

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/bex_vm_types/src/bytecode.rs (1)

185-186: ⚠️ Potential issue | 🟠 Major

Preserve the serialized Instruction discriminants.

Instruction is Borsh-serialized without explicit discriminant pinning (unlike OpCode which uses #[borsh(use_discriminant = true)]), and inserting VirtualCall before Throw shifts the ordinal for every later variant. Existing packed bytecode (embedded in executables via baml pack) will deserialize incorrectly: bytes that previously decoded to Throw will now decode to VirtualCall, silently corrupting instruction interpretation. Move VirtualCall to the end of the enum to match the OpCode pattern, or add an explicit version field to Program/Bytecode with migration logic.

🤖 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_types/src/bytecode.rs` around lines 185 - 186,
The Instruction enum lacks explicit discriminant pinning for Borsh
serialization, so adding VirtualCall before Throw shifts the ordinal values of
all subsequent variants, breaking deserialization of existing packed bytecode.
Move the VirtualCall variant to the end of the Instruction enum definition to
preserve the existing discriminant values for all other variants and maintain
backward compatibility with bytecode already embedded in executables.
🧹 Nitpick comments (5)
baml_language/crates/baml_compiler2_mir/src/builder.rs (1)

350-353: ⚡ Quick win

Clarify the receiver position when method type args are present.

Line 351 says the receiver is the first args entry, but the API reserves args[..ntypeargs] for method-level type arguments, so the receiver is args[ntypeargs].

Proposed documentation fix
-    /// resolved at runtime from the receiver's concrete type (the first `args`
-    /// entry) against `iface`. Used for statically-undetermined receivers
+    /// resolved at runtime from the receiver's concrete type (the first value
+    /// argument, `args[ntypeargs]`) against `iface`. Used for statically-undetermined receivers
🤖 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/builder.rs` around lines 350 -
353, The documentation comment for the open-world virtual interface-method call
function needs to be updated to correctly describe the receiver position.
Currently, the comment states the receiver is the first args entry, but this is
only accurate when there are no method-level type arguments. Update the comment
to clarify that the API reserves args[..ntypeargs] for method-level type
arguments, and therefore the receiver is located at args[ntypeargs], not at
args[0]. This will prevent confusion when method type arguments are present.
baml_language/crates/bex_vm_types/src/bytecode.rs (1)

2069-2073: ⚡ Quick win

Add a unit test for VirtualCall compact encoding.

This opcode has the new u16 + u16 operand shape; cover size, operand order, TryFrom, and display so nargs/ntypeargs cannot be swapped silently. As per coding guidelines, Rust changes should prefer unit tests where possible and run cargo test --lib.

Proposed unit test
+    #[test]
+    fn encode_virtual_call_operands() {
+        let instr = Instruction::VirtualCall {
+            nargs: 3,
+            ntypeargs: 2,
+        };
+        let bc = make_bytecode(vec![instr], vec![]);
+        let compact = bc.lower_to_compact();
+
+        assert_eq!(compact.code.len(), 5);
+        assert_eq!(compact.code[0], OpCode::VirtualCall as u8);
+        assert_eq!(u16::from_le_bytes([compact.code[1], compact.code[2]]), 3);
+        assert_eq!(u16::from_le_bytes([compact.code[3], compact.code[4]]), 2);
+        assert_eq!(OpCode::try_from(compact.code[0]), Ok(OpCode::VirtualCall));
+        assert_eq!(
+            instr.to_string(),
+            "VIRTUAL_CALL nargs=3 ntypeargs=2"
+        );
+    }

Also applies to: 2399-2399

🤖 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_types/src/bytecode.rs` around lines 2069 - 2073,
Add a unit test for the VirtualCall instruction encoding to verify the compact
bytecode representation. The test should create a VirtualCall instance with
specific nargs and ntypeargs values, encode it through the existing bytecode
serialization logic, and verify that the resulting bytes have the correct length
(4 bytes for two u16 values), that operands are encoded in the correct order
(nargs first, then ntypeargs as shown in the encoding block), and that TryFrom
deserialization correctly reconstructs the original instruction without swapping
the operand values. Include assertions validating the Display trait
implementation to ensure the instruction is formatted correctly for debugging
purposes.

Source: Coding guidelines

baml_language/crates/baml_compiler2_emit/src/emit.rs (1)

2112-2112: 💤 Low value

Consider adding a debug assertion for arithmetic safety.

The subtraction args.len() - ntypeargs will panic on underflow in debug builds (or wrap in release). While MIR should always be well-formed with args.len() >= ntypeargs, a debug assertion documents the invariant and aids debugging if upstream MIR construction has a bug.

🛡️ Proposed defensive assertion
+                debug_assert!(
+                    args.len() >= *ntypeargs,
+                    "VirtualCall: args.len() ({}) must be >= ntypeargs ({})",
+                    args.len(),
+                    ntypeargs
+                );
                 let nargs = args.len() - ntypeargs;
🤖 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_emit/src/emit.rs` at line 2112, The
subtraction operation `args.len() - ntypeargs` lacks a debug assertion to verify
the invariant that args.len() must be greater than or equal to ntypeargs. Add a
debug assertion immediately before this subtraction to ensure this precondition
holds, which will document the expected invariant and help catch any upstream
MIR construction bugs during development.
baml_language/crates/bex_vm/src/vm.rs (1)

5483-5487: 🏗️ Heavy lift

Avoid global name scans in the VirtualCall hot path.

find_function_by_name scans all globals for every virtual dispatch. Since method.fqn is known when building the runtime impl registry, store a resolved GlobalIndex/function pointer in MethodImpl and jump directly here.

🤖 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 5483 - 5487, The
VirtualCall hot path is performing an expensive global name scan via
find_function_by_name for every virtual dispatch. Instead, modify the MethodImpl
struct to store a pre-resolved GlobalIndex or function pointer during runtime
impl registry construction. Then replace the find_function_by_name call in the
VirtualCall handling block with a direct access to this pre-resolved reference
stored in the method field. This eliminates the repeated global scans and moves
the lookup cost to initialization time.
baml_language/crates/bex_vm/tests/interface_registry.rs (1)

26-29: ⚡ Quick win

contains-based impl-rule matching is too fuzzy for a white-box assertion helper.

Substring matching can pick the wrong rule as more types are added, which can make these tests pass for the wrong reason.

Proposed fix
         .find(|rule| {
             let pat = rule.for_ty_pattern.to_string();
-            pat == for_type || (pat.contains(for_type) && !pat.contains("$stream"))
+            let normalized = pat.strip_suffix("$stream").unwrap_or(&pat);
+            normalized == for_type
+                || normalized.rsplit('.').next() == Some(for_type)
         })
🤖 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/tests/interface_registry.rs` around lines 26 -
29, The `find` closure that matches rules based on `rule.for_ty_pattern` uses
substring matching with `contains`, which is too imprecise and can match the
wrong rule as more types are added. Replace the fuzzy substring-based matching
logic with exact pattern matching that properly compares the pattern against the
intended type without relying on partial string containment checks. Consider
implementing a more precise matching strategy that handles the pattern matching
semantics correctly rather than just checking if one string contains another.
🤖 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_builtins2_codegen/src/codegen.rs`:
- Around line 1733-1753: The is_container closure only detects top-level List,
Map, and Uint8Array types but fails to detect containers wrapped in Optional
types like Option<List<T>>. This causes the function to undercount container
parameters and potentially miss deadlock scenarios. Update the is_container
closure to recursively check if a type is Optional and if so, inspect the
wrapped inner type to detect containers that are nested within Option wrappers,
ensuring all container parameters are properly counted regardless of whether
they are directly or indirectly wrapped in Optional.

In `@baml_language/crates/baml_builtins2_codegen/src/extract.rs`:
- Around line 512-517: The generic parameters collection in the code around
impl_def.generic_params is only capturing implementation-level generics but
missing method-level generics. When collecting impl_generics using
impl_def.generic_params, also iterate through and include any generic parameters
that exist at the method level to ensure all generics (both implementation and
method level) are properly propagated to NativeBuiltin.generics. Apply this same
fix to all similar locations where generics are being collected (including the
areas mentioned at lines 550-577) so that method generic parameters are not
treated as concrete types and are included in the final generics list.
- Around line 614-626: The function `type_expr_to_baml_type_with_self` only
handles bare `Self` and falls through to `type_expr_to_baml_type` for all other
cases, which leaves nested forms like `Self[]`, `map<string, Self>`, or `Self?`
unresolved. To fix this, instead of just checking for top-level `Self`, you need
to recursively process the entire TypeExpr structure to replace all occurrences
of `Self` with `self_baml` at any nesting level. For container types, extract
their inner types and recursively call `type_expr_to_baml_type_with_self` on
those inner types before reconstructing the container with the resolved inner
types. Apply the same recursive logic for optional or wrapped types before
applying outer type wrappers.

In `@baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/comparison.baml`:
- Around line 147-156: In the Equals implementations for T[] and map<K, V>,
replace the calls to baml.ops.equals_equals(self, other) with direct comparison
logic. For the array implementation, compare elements sequentially using the
element type's Equals trait. For the map implementation, compare key-value pairs
directly. This avoids the circular dispatch where equals_equals would call back
to Equals.eq, preventing infinite recursion.

In `@baml_language/crates/baml_compiler2_emit/src/lib.rs`:
- Around line 352-357: The rules are currently being bucketed and sorted using
only the for_ty_pattern as the key, but when a class implements the same
interface at multiple instantiations (e.g., Converter<int> and
Converter<float>), this creates ties that rely on insertion order from unordered
maps, breaking deterministic output. Update the sort key to include the full
interface instantiation alongside for_ty_pattern, not just the pattern alone.
This applies to the rule sorting/keying logic referenced in the comment block
and also to any other places where similar bucketing occurs (around the
locations mentioned in the comment).

In `@baml_language/crates/baml_compiler2_mir/src/lower.rs`:
- Around line 8923-8938: The iface_template is currently built using
TyTemplate::Concrete with RuntimeTy::Interface and convert_tir_ty_for_runtime
conversions, which preserves caller generics as bare RuntimeTy::TypeVar instead
of TypeArgRef, causing unresolved interface keys in virtual calls on generic
Converter types. Replace the TyTemplate::Concrete(RuntimeTy::Interface(...))
construction with a call to ty_to_template on the TIR interface view to ensure
caller frame type arguments are properly substituted at runtime.
- Around line 8941-8949: The virtual_call method is receiving the destination
directly, but it should normalize the destination to a local variable first,
similar to how regular calls are handled. Instead of passing dest.clone() as the
destination to the virtual_call invocation, create a temporary local variable as
the destination for the virtual_call, and then after the resume block completes,
add a copy operation from that temporary local to the actual dest projection if
dest is not already a local. This ensures virtual interface calls handle complex
destinations like fields, indices, or captures consistently with regular call
constraint handling.
- Around line 5861-5876: The issue is that `eq_dest` can be a complex Place like
`Place::Field` or `Place::Index` for both `Eq` and `Ne` operations, but the
`call` instruction expects a `Place::Local` destination. Currently, a temporary
is only created for `Ne` operations. Modify the logic to check whether `dest` is
a `Place::Local` regardless of the operator type: if it is not a local, create a
temporary as the call destination for both `Eq` and `Ne` cases, then add a copy
instruction after the call to transfer the result from the temporary back to the
original `dest` place.

In `@baml_language/crates/baml_lsp2_actions/src/check.rs`:
- Around line 4550-4560: The `expand_type_alias` call in the map operation on
line 4558 only expands top-level aliases and does not handle nested aliases
within compound types like Container<List<A>>. Modify the expansion logic to
recursively expand all nested type aliases so that compound types with aliased
type parameters are fully resolved. This ensures that semantically equivalent
types like Container<List<A>> and Container<List<int>> (where A = int) generate
identical keys when used in the lower_path_generic_args function and subsequent
type_arg_key generation.
- Around line 4453-4457: The loops iterating over members.required_methods are
only checking if methods are in provided_method_names before skipping them, but
they also need to check if a default implementation exists in
members.default_methods. Modify the condition where you check if
provided_method_names.contains(req_name) to also check if req_name exists in
members.default_methods, so that requirements are properly satisfied by either
explicit implementations or default implementations from parent types. Apply
this fix to all similar loops that validate required methods (note the comment
mentions this also applies to additional locations around line 4794-4801).

In `@baml_language/crates/baml_tests/tests/interfaces.rs`:
- Around line 7640-7648: The test malformed_impls_do_not_spuriously_overlap only
asserts that there are no interface errors, which could allow the test to pass
vacuously if unresolved-type validation regresses. Add additional assertions
after the assert_no_interface_errors call to verify that unresolved-type
diagnostics are actually present for the Nonexistent1 and Nonexistent2 types,
and ensure that error E0132 (the spurious overlap error) is absent from the
diagnostics. This will prevent the test from passing silently when type
validation logic changes.

In `@baml_language/crates/bex_vm_types/src/bytecode.rs`:
- Around line 958-963: The comment for the VirtualCall instruction incorrectly
describes the stack order. The interface type (Object::Type) and method-name
string are actually placed above the value args on the stack and are popped
first, not below as the current comment states. Update the VirtualCall comment
to accurately reflect that iface_type and method_name are positioned above the
args on the stack and are popped before processing the arguments.

In `@baml_language/crates/bex_vm_types/src/types.rs`:
- Around line 187-203: The new `interface_impls` field added to the `Program`
struct is a non-skipped Borsh-serialized field, which breaks deserialization of
previously compiled binaries. Determine which of the three approaches to take:
(1) add a version field to PackEnvelope and implement migration logic in the
extract_envelope() function to handle old wire formats, (2) document that old
compiled binaries are no longer supported, or (3) mark the interface_impls field
with #[borsh(skip)] if the field can be populated at runtime initialization
instead of deserialization. Verify your choice is compatible with how
extract_envelope() deserializes PackEnvelope and implement the necessary changes
to prevent deserialization failures.

In `@baml_language/crates/bex_vm/src/package_baml/ops.rs`:
- Around line 303-307: The cycle detection logic in the visited set
normalization is preventing both orderings of a comparison pair from being
checked separately. Instead of normalizing the key to a canonical form using the
comparison operator (if pa < pb), preserve the actual operand order directly as
the key. This ensures that both (pa, pb) and (pb, pa) are treated as distinct
entries in the visited set, allowing both orderings to be evaluated even if the
user-defined Equals.eq function is non-symmetric. Apply this same change to all
locations where similar key normalization occurs (also in the section mentioned
at lines 541-549).

In `@baml_language/crates/bex_vm/src/package_baml/resolve.rs`:
- Around line 116-145: The fallback mechanism in resolve_implements_rule is
incorrectly storing a mismatched rule as a fallback even when iface_args is
non-empty and the rule's interface_args do not match. The fallback is then
returned, allowing a mismatch like resolving Iface<string> through an Iface<int>
implementation. Only set the fallback to the first applicable rule when
iface_args.is_empty() is true; otherwise, if no rule's interface_args exactly
match the requested iface_args, the function should return None instead of
falling back to a mismatched rule.

In `@baml_language/crates/bex_vm/src/vm.rs`:
- Around line 5467-5477: The resolve_implements_rule call accepts a fallback
match even when iface_args is non-empty and the returned rule's interface
arguments don't match the requested iface_args, leading to incorrect impl
dispatch. After the resolve_implements_rule call succeeds and returns a rule and
bound_args, add validation to verify that the returned rule's realized interface
arguments match the provided iface_args. If they don't match, treat this as an
unresolved virtual call error instead of silently using the mismatched impl.
Alternatively, constrain the resolver to only use fallback candidates when
iface_args is empty or erased.
- Around line 1399-1414: The match arm in the virtual call resolution logic
handling Object::Array and Object::Map kinds currently uses unimplemented!()
which panics when container receivers are dispatched on, but the stdlib now
supports container interface methods. Replace the unimplemented!() call with
proper error handling by either implementing container virtual dispatch with
runtime type tags to track element types at the Value level, carrying the
realized receiver type information into the VirtualCall structure, or adding
validation during the lowering phase to reject unsupported container receiver
calls before they reach the VM. Choose the approach that aligns best with the
existing architecture.

In `@baml_language/crates/bex_vm/tests/comparison_driver.rs`:
- Around line 28-33: The infinite loop in the `run_bool` function can hang
indefinitely if the VM repeatedly returns `VmExecState::EarlyYield`, which
stalls the test suite instead of producing a clear failure. Add an iteration
counter to the loop and establish a maximum iteration limit (e.g., 10000
iterations). When the loop exceeds this limit, panic with a descriptive message
indicating that the VM execution did not complete within the expected number of
iterations, which will provide clear test failure feedback instead of hanging.

In `@baml_language/crates/bex_vm/tests/ops_comparison.rs`:
- Around line 85-90: The test currently verifies that ordering comparisons with
NaN on the left operand (nan, one) return false for FLOAT_LT, FLOAT_GT,
FLOAT_GE, and FLOAT_LE operations, but does not test NaN on the right operand.
Add additional assertions after the existing ones that mirror these tests but
with the operands reversed (one, nan) to ensure the float comparison operations
correctly handle NaN as the right-hand operand according to the IEEE standard.

---

Outside diff comments:
In `@baml_language/crates/bex_vm_types/src/bytecode.rs`:
- Around line 185-186: The Instruction enum lacks explicit discriminant pinning
for Borsh serialization, so adding VirtualCall before Throw shifts the ordinal
values of all subsequent variants, breaking deserialization of existing packed
bytecode. Move the VirtualCall variant to the end of the Instruction enum
definition to preserve the existing discriminant values for all other variants
and maintain backward compatibility with bytecode already embedded in
executables.

---

Nitpick comments:
In `@baml_language/crates/baml_compiler2_emit/src/emit.rs`:
- Line 2112: The subtraction operation `args.len() - ntypeargs` lacks a debug
assertion to verify the invariant that args.len() must be greater than or equal
to ntypeargs. Add a debug assertion immediately before this subtraction to
ensure this precondition holds, which will document the expected invariant and
help catch any upstream MIR construction bugs during development.

In `@baml_language/crates/baml_compiler2_mir/src/builder.rs`:
- Around line 350-353: The documentation comment for the open-world virtual
interface-method call function needs to be updated to correctly describe the
receiver position. Currently, the comment states the receiver is the first args
entry, but this is only accurate when there are no method-level type arguments.
Update the comment to clarify that the API reserves args[..ntypeargs] for
method-level type arguments, and therefore the receiver is located at
args[ntypeargs], not at args[0]. This will prevent confusion when method type
arguments are present.

In `@baml_language/crates/bex_vm_types/src/bytecode.rs`:
- Around line 2069-2073: Add a unit test for the VirtualCall instruction
encoding to verify the compact bytecode representation. The test should create a
VirtualCall instance with specific nargs and ntypeargs values, encode it through
the existing bytecode serialization logic, and verify that the resulting bytes
have the correct length (4 bytes for two u16 values), that operands are encoded
in the correct order (nargs first, then ntypeargs as shown in the encoding
block), and that TryFrom deserialization correctly reconstructs the original
instruction without swapping the operand values. Include assertions validating
the Display trait implementation to ensure the instruction is formatted
correctly for debugging purposes.

In `@baml_language/crates/bex_vm/src/vm.rs`:
- Around line 5483-5487: The VirtualCall hot path is performing an expensive
global name scan via find_function_by_name for every virtual dispatch. Instead,
modify the MethodImpl struct to store a pre-resolved GlobalIndex or function
pointer during runtime impl registry construction. Then replace the
find_function_by_name call in the VirtualCall handling block with a direct
access to this pre-resolved reference stored in the method field. This
eliminates the repeated global scans and moves the lookup cost to initialization
time.

In `@baml_language/crates/bex_vm/tests/interface_registry.rs`:
- Around line 26-29: The `find` closure that matches rules based on
`rule.for_ty_pattern` uses substring matching with `contains`, which is too
imprecise and can match the wrong rule as more types are added. Replace the
fuzzy substring-based matching logic with exact pattern matching that properly
compares the pattern against the intended type without relying on partial string
containment checks. Consider implementing a more precise matching strategy that
handles the pattern matching semantics correctly rather than just checking if
one string contains another.
🪄 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: 91640b55-6760-4013-94cb-5a54db88fe94

📥 Commits

Reviewing files that changed from the base of the PR and between 1581adc and 633304c.

⛔ Files ignored due to path filters (40)
  • baml_language/crates/baml_cli/src/snapshots/baml_cli__describe_command_tests__render_builtin_package_listing.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/bigints.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/csv.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/floats.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_to_from_string.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/optional_function_parameters.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/reflect_type_of.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/reflect_type_of_generic.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/baml_src/type_reflection.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/compiler2_mir/baml_tests__compiler2_mir__optional_named_gap_and_explicit_null.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__assert_std__/baml_tests__compiles____assert_std____04_5_mir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/__assert_std__/baml_tests__compiles____assert_std____06_codegen.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
  • baml_language/crates/baml_tests/snapshots/compiles/byte_string_literals/baml_tests__compiles__byte_string_literals__04_5_mir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/byte_string_literals/baml_tests__compiles__byte_string_literals__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/optional_function_parameters/baml_tests__compiles__optional_function_parameters__04_5_mir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/compiles/optional_function_parameters/baml_tests__compiles__optional_function_parameters__06_codegen.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/format_checks/baml_tests__diagnostic_errors__format_checks__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/format_checks/baml_tests__diagnostic_errors__format_checks__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__01_lexer__numeric_invariance.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/numeric_invariance/baml_tests__diagnostic_errors__numeric_invariance__10_formatter__numeric_invariance.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/simple_type_error/baml_tests__diagnostic_errors__simple_type_error__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/simple_type_error/baml_tests__diagnostic_errors__simple_type_error__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_name_type_error/baml_tests__diagnostic_errors__test_expr_name_type_error__04_tir.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/snapshots/diagnostic_errors/test_expr_name_type_error/baml_tests__diagnostic_errors__test_expr_name_type_error__05_diagnostics.snap is excluded by !**/*.snap
  • baml_language/crates/baml_tests/src/compiler2_tir/snapshots/baml_tests__compiler2_tir__phase5__snapshot_baml_package_items.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
  • baml_language/sdks/nodejs/bridge_nodejs/dist/proto/baml_cffi.js is excluded by !**/dist/**
📒 Files selected for processing (46)
  • baml_language/crates/baml_builtins2/baml_std/baml/ns_ops/comparison.baml
  • baml_language/crates/baml_builtins2/src/lib.rs
  • baml_language/crates/baml_builtins2_codegen/src/codegen.rs
  • baml_language/crates/baml_builtins2_codegen/src/extract.rs
  • baml_language/crates/baml_compiler2_ast/src/ast.rs
  • baml_language/crates/baml_compiler2_emit/src/analysis.rs
  • baml_language/crates/baml_compiler2_emit/src/emit.rs
  • baml_language/crates/baml_compiler2_emit/src/lib.rs
  • baml_language/crates/baml_compiler2_emit/src/stack_carry.rs
  • baml_language/crates/baml_compiler2_hir/src/package.rs
  • baml_language/crates/baml_compiler2_mir/src/builder.rs
  • baml_language/crates/baml_compiler2_mir/src/ir.rs
  • baml_language/crates/baml_compiler2_mir/src/lower.rs
  • baml_language/crates/baml_compiler2_mir/src/optimize.rs
  • baml_language/crates/baml_compiler2_mir/src/pretty.rs
  • 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/interfaces.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_bigints/bigints.baml
  • baml_language/crates/baml_tests/baml_src/ns_floats/floats.baml
  • baml_language/crates/baml_tests/projects/diagnostic_errors/numeric_invariance/numeric_invariance.baml
  • baml_language/crates/baml_tests/src/compiler2_tir/inference.rs
  • baml_language/crates/baml_tests/src/compiler2_tir/phase3a.rs
  • baml_language/crates/baml_tests/tests/interfaces.rs
  • baml_language/crates/baml_tests/tests/interfaces_associated_types.rs
  • baml_language/crates/baml_type/src/interface.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/bex_engine/src/lib.rs
  • baml_language/crates/bex_vm/src/debug.rs
  • baml_language/crates/bex_vm/src/package_baml/json.rs
  • baml_language/crates/bex_vm/src/package_baml/mod.rs
  • baml_language/crates/bex_vm/src/package_baml/ops.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/vm.rs
  • baml_language/crates/bex_vm/tests/comparison_driver.rs
  • baml_language/crates/bex_vm/tests/interface_registry.rs
  • baml_language/crates/bex_vm/tests/ops_comparison.rs
  • baml_language/crates/bex_vm_types/src/bytecode.rs
  • baml_language/crates/bex_vm_types/src/errors.rs
  • baml_language/crates/bex_vm_types/src/types.rs
  • baml_language/sdks/nodejs/bridge_nodejs/typescript_src/proto/baml_cffi.js

Comment thread baml_language/crates/bex_vm/src/vm.rs Resolved
Comment thread baml_language/crates/bex_vm/src/vm.rs Resolved
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 17, 2026 19:02 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 17, 2026 19:14 Inactive
- Path callees should also be able to do virtual calls
- Class inherent method cannot override interface `implements` methods
- Class inherent methods cannot satisfy an interface contract: ONLY
  methods inside the `implements` block (or defaulted in) can do so.
- Methods from required interfaces of interface-existentials should
  dispatch with the declaring interface not the requiring interface.
- Coderabbit suggestions
- Better diagnostic messages for invalid operator usage
- Add some regression tests
@vercel
vercel Bot temporarily deployed to Preview – beps June 17, 2026 20:56 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 June 17, 2026 21:01 Inactive
@2kai2kai2
2kai2kai2 added this pull request to the merge queue Jun 17, 2026
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle June 17, 2026 21:14 Inactive
Merged via the queue into canary with commit 9c5fed4 Jun 17, 2026
52 checks passed
@2kai2kai2
2kai2kai2 deleted the kai/comparison branch June 17, 2026 21:17
codeshaunted added a commit that referenced this pull request Jun 18, 2026
…olation

Resolves 4 post-merge test failures (no source conflicts — all in generated
snapshots / test expectations):

- numeric_invariance lexer snapshot: regenerated — backtick now lexes as a
  `Backtick` token (this branch's feature) instead of `Error`.
- bytecode_display_{expanded,unoptimized}: regenerated — canary grew the
  builtin function table (comparison ops / interface fixes) so call indices
  shifted, plus this branch's auto-derived `to_string` methods now appear.
- phase3a {new_mode_failures_have_good_diagnostics, nested_lambda_diagnostic_
  has_real_span}: updated the asserted substring from `operator \`Add\`` to
  `operator \`+\`` to match canary's improved arithmetic diagnostic (#3788),
  which now prints the user-facing operator symbol.

Full suite green: 6263 passed, 0 snapshot drift.

This branch was previously deployed

3 inactive deployments
Preview – promptfiddle — 19161cf2 Deployed Jun 17, 2026 by vercel[bot]
Preview – promptfiddle2 — 19161cf2 Deployed Jun 17, 2026 by vercel[bot]
Preview – beps — 19161cf2 Deployed Jun 17, 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