Skip to content

feat(tir): mounted-blob packages resolve in type positions (BEP-066 slice 6a, PR 3) - #4329

Merged
antoniosarosi merged 5 commits into
antonio/s6a-impls-exportfrom
antonio/s6a-type-consumption
Aug 7, 2026
Merged

antoniosarosi merged 5 commits into
antonio/s6a-impls-exportfrom
antonio/s6a-type-consumption

Conversation

@antoniosarosi

@antoniosarosi antoniosarosi commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

BEP-066 slice-6a stack, PR 3 of 5 — chained on #4327. The first consumer PR: a package mounted as a serialized PackageInterface blob (no source in the DB) now fully resolves in type positions; calls land in PR 4 (reserved diagnostic E0158 until then).

The mount seam

  • MountedPackages Salsa input (alias → borsh(PackageInterface)), present-from-construction like the B-694 seeds; served by a package_interface arm below the untouched stdlib seed; corrupt blobs fall through to ordinary unresolved diagnostics.
  • Dependency policy: user packages depend on every mounted name; mounts see only the stdlib. Reserved names (baml, user, …) are ignored outright — a blob can never shadow the stdlib or the user package.

Consumption

  • resolve_type_in returns Own(Definition) | Foreign(&ExportedType); lower_path's Foreign arm mirrors Own exactly (arity, binding validation, existential default-filling by substitution of the pre-lowered symbolic-Self defaults — no double-fill, completeness checks).
  • Fact queries split seed-or-source: aliases, enum variants (+ exhaustiveness), class fields/methods, assoc bounds/defaults/name-sets, interface_requires via the exported pre-flattened closure (fail-closed), UFCS/value-reference typing.
  • Impl substrate: blob ExportedImpl rows materialize into native ImplData (ImplInterfaceTarget::{Source,Mounted}, ImplRef::{Loc,Mounted} — the loc-free ResolvedImpl twin); all five enumerators + coherence run unchanged over one package_impls seam; blob impls are pre-checked and never re-validated; user impls of mounted interfaces get full conformance checking. Coherence attributes primary-only at the user's impl with the dep side rendered structurally.
  • Schema refinement: ExportedType::Interface.methods → required_methods/default_methods (E0113 coverage is undecidable from a merged list).
  • PR 1's interface-row guards became the mounted gate: rows resolve iff mounted; source-backed dep resolution is byte-identical (tested both ways).

Proof

12 new mounted-consumption tests (class/interface/enum/alias/impl/bound/negative shapes + coherence overlap + E0158 both-ways) · full baml_tests exit 0 (lib 1511/0) · tir 324/0 · project 82/0 · bytecode_cache 43/0 · zero snapshot churn · fmt/clippy clean on diff.

For PR 4 (queued)

MemberResolution::External + MIR symbolic callees, blob-impl method dispatch + structural {iface}$for${target} reconstruction, the $stream-rows policy, and the conservative gaps listed in the commit message.

Summary by CodeRabbit

  • New Features

    • Added support for resolving types, interfaces, implementations, aliases, enum variants, fields, and methods from mounted dependency packages.
    • Added package discovery and serialized interface loading for source-less dependencies.
    • Added validation for mounted package coherence, generics, associated types, interface requirements, and default methods.
  • Bug Fixes

    • Prevented crashes when source locations are unavailable.
    • Added diagnostic E0158 for unsupported calls into mounted packages.
    • Improved conflict diagnostics for mounted dependency implementations.
  • Tests

    • Expanded coverage for mounted packages, conformance, aliases, exhaustiveness, and error handling.

…lice 6a, PR 3)

The first CONSUMER PR: a package mounted as a borsh(PackageInterface)
blob — with NO source files — now resolves at check level in every TYPE
position, contributes its impls table to membership/bounds/coherence,
and rejects actual CALLS with a dedicated reserved diagnostic (call
lowering + MIR land in the next PR). Source-backed resolution is
byte-identical: full baml_tests suite green with zero snapshot churn.

The mount seam:
- baml_workspace::MountedPackages, a Salsa input (alias ->
  borsh(PackageInterface)) with the SeededStdlibInterface
  present-from-construction discipline; ProjectDatabase grows
  set_mounted_packages + an add_compiler2_virtual_file fixture hook
  (library files under <builtin>/<pkg>/ ride Compiler2ExtraFiles, the
  only channel compiler2_all_files accepts them from).
- package_dependencies: user packages additionally depend on every
  mounted name; a mounted package keeps the stdlib list only (mounts do
  not see each other). Reserved names (the hardcoded stdlib arms plus
  user/root/env) are ignored entirely — a blob can never shadow the
  stdlib or the user's own package (RESERVED_PACKAGE_NAMES, kept in
  lockstep with the hardcoded arms).
- package_interface serves the mounted blob through a parallel arm
  below the B-694 stdlib seed (untouched); a corrupt blob falls through
  to the honest — empty — derivation.

Type-position dualization (the keystone):
- resolve_type_in returns ResolvedTypeDefinition: Own(Definition) |
  Foreign(&ExportedType) — a mounted prefix consults the blob's rows
  instead of raw package_items. Threaded through
  TypeExprContext::resolve_type (single impl) into lower_path, whose
  new Foreign arm mirrors the Own arms exactly: Class arity from the
  row's generic_params; the Interface arm validates written bindings,
  eagerly fills pre-lowered symbolic-Self defaults by pure substitution
  (realize_associated_default), and enforces existential completeness;
  Enum/TypeAlias reject generic args; the enum-variant fallback
  verifies against the exported variant list. Mounted $stream
  companions deliberately stay unresolvable (blobs export no $stream
  rows; the fallback consults source items only).
- The PR-1 interface-row guards become a mounted gate: dep interface
  rows RESOLVE for mounted packages; source-backed deps keep the loc
  path (baml.iter.Iterator still resolves via source items).

Fact-query seed-or-source splits (blob-backed for mounted packages):
alias_def + normalized_alias_map (ExportedType::TypeAlias.resolved;
package_resolved_aliases already read dep rows), enum_variants +
enum_variant_names, class fields (class_all_fields_ordered) and
methods (lookup_class_method -> ClassMethodLookup::ForeignFound, typed
from the exported signature), existential_associated_default,
associated_type_declared_bound, interface_declares_member,
interface_associated_type_names_for_qtn, and interface_requires (the
pre-flattened exported closure realized by substitution; root-pinned
projections stay symbolic — fail-closed).

The impl substrate (the package_impls abstraction):
- ExportedType::Interface splits methods into required_methods /
  default_methods (schema change over PR 1): E0113 coverage and
  method-default fallback are undecidable from a merged list.
- ImplData.interface becomes ImplInterfaceTarget::Source(loc) |
  Mounted(qtn) with interface_loc()/interface_qtn() accessors.
- mounted_impl_datas materializes blob ExportedImpl rows into the
  checker's native ImplData (loc-free: empty methods/diagnostics —
  blob impls are pre-checked and never re-validated); package_impls
  unifies loc-backed blocks and blob rows as the single enumeration
  seam for type_implements_interface, get_implements_block(_symbolic),
  impls_for_type, and first_failing_impl_bound. ResolvedImpl carries
  ImplRef (Loc | Mounted{pkg,index}) with data()/impl_loc(); consumers
  that must record locs for MIR (concrete method dispatch, interface
  field views, LSP handles) skip mounted rows until the call PR.
- Coherence consumes blob rows span-less: CoherenceViolation.secondary
  becomes Option<Span> plus a structural secondary_desc ("implement I
  for T"), attributed primary-only at the user's impl.

User impls of mounted interfaces:
- impl_data grows a mounted arm (mounted_impl_data): the target
  resolves through the lowered Ty::Interface head; associated bindings
  lower with Self rigid at the already-resolved pins and defaults fill
  from the row; the full name/membership rule set runs against the row
  (E0113/E0115/E0124/E0126/E0128/E0129/E0130, binding hygiene).
- validate_impl_signatures grows the type-level twin
  (validate_mounted_impl_signatures): E0116 field conformance, the
  loc-free header gates (E0138/E0135/E0139), E0120 signature
  conformance against the exported symbolic-Self rows (throws compared
  on the declared clause, lower_signature's Missing convention), the
  bound-addition rule from exported generic_param_bounds, E0125 from
  the pre-flattened requires closure (transitive — strictly more
  complete than the source arm's direct clauses), and associated-type
  bound satisfaction.

Calls are reserved, references type: resolve_package_item /
infer_multi_segment_path answer pkg.path from the blob (functions type
from ExportedFunction with NO MemberResolution recorded; types, enum
variants, and UFCS methods mirror the raw-items arm), and the call
arms report the new E0158 MountedPackageCallUnsupported for any callee
marked foreign — so `let f = app.add` types while `app.add(1, 2)` is
rejected with "calls into mounted packages are not supported yet".

Tests (baml_tests compiler2_tir::package_interface::mounted): a
fixture library compiled under <builtin>/app/, its blob mounted in a
fresh DB as `app` with no source — class/interface/alias/enum type
positions, T extends app.I bounds and existential assignment through
blob impls, ordering via the blob's Equals/Compare rows, user impls of
a mounted interface (clean + missing-method + signature-mismatch),
match exhaustiveness over a mounted enum, coherence overlap with a
mounted blanket impl (primary-only attribution), unresolved-name and
reserved-call negatives, and the PR-1 guard test now proving interface
rows resolve for mounted deps only.

Gate: baml_tests full suite exit 0 (lib 1511 passed / 0 failed), zero
snapshot churn; baml_compiler2_tir 324; baml_project 82; baml_cli
bytecode_cache 43; fmt + clippy clean on the diff. (--no-verify:
pre-commit cargo hooks fail on the environmental mise config-trust
error in this worktree; real fmt/clippy verified clean.)
@vercel

vercel Bot commented Aug 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 Aug 7, 2026 5:39am
promptfiddle2 Ready Ready Preview Aug 7, 2026 5:39am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cf8a29db-d63c-4710-8642-1c52e885126e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Compiler2 now consumes serialized mounted PackageInterface data. It resolves mounted types, members, associated types, implementations, aliases, enums, and coherence rules. Direct mounted-package calls produce diagnostic E0158.

Mounted package compiler support

Layer / File(s) Summary
Mounted package inputs and export contracts
baml_language/crates/baml_workspace/src/lib.rs, baml_language/crates/baml_project/src/db.rs, baml_language/crates/baml_compiler2_hir/src/package.rs, baml_language/crates/baml_compiler2_tir/src/package_interface.rs
Salsa inputs expose serialized mounted interfaces. Reserved names are filtered. Interface exports separate required and default methods.
Mounted type and member resolution
baml_language/crates/baml_compiler2_tir/src/lower_type_expr.rs, baml_language/crates/baml_compiler2_tir/src/builder.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/unify.rs
Mounted export rows support type lowering, members, aliases, enums, associated types, requirements, defaults, and generic substitution.
Mounted implementation resolution and coherence
baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs, baml_language/crates/baml_compiler2_tir/src/interfaces/coherence.rs, baml_language/crates/baml_compiler2_tir/src/builder/interface_resolution.rs, baml_language/crates/baml_surface/src/*
Implementation lookup supports mounted targets and source-backed targets. Mounted implementations receive conformance and signature validation. Coherence diagnostics support span-less implementations.
Mounted call diagnostics and compatibility
baml_language/crates/baml_compiler2_tir/src/builder.rs, baml_language/crates/baml_compiler2_tir/src/infer_context.rs, baml_language/crates/baml_compiler_diagnostics/src/diagnostic.rs, baml_language/crates/baml_lsp2_actions/src/check.rs, baml_language/crates/baml_compiler2_mir/src/lower.rs
Mounted callable references are tracked and direct calls report MountedPackageCallUnsupported. Source-only interface and handle paths now use optional locations.

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

Sequence Diagram(s)

sequenceDiagram
  participant ProjectDatabase
  participant PackageInterface
  participant TIRResolver
  participant Diagnostic
  ProjectDatabase->>PackageInterface: provide serialized mounted blob
  TIRResolver->>PackageInterface: resolve exported type or implementation row
  PackageInterface-->>TIRResolver: return pre-lowered metadata
  TIRResolver->>Diagnostic: report unsupported mounted call
Loading

Possibly related PRs

Poem

A rabbit loads blobs through compiler streams,
Exported rows shape types and dreams.
Implementations cross the package wall,
E0158 answers calls.
Source-backed handles keep their place.

🚥 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 and concisely describes the primary change: resolving mounted package blobs in type positions.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch antonio/s6a-type-consumption

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

github-actions Bot commented Aug 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.

@vercel
vercel Bot temporarily deployed to Preview – beps August 6, 2026 01:31 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps August 6, 2026 01:35 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 August 6, 2026 01:42 Inactive
@vercel
vercel Bot temporarily deployed to Preview – beps August 6, 2026 01:45 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 August 6, 2026 01:52 Inactive
@github-actions

github-actions Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

Binary size checks passed

✅ 7 passed

Artifact Platform File Gzip Gated on Baseline Delta Status
✅ baml-cli Linux 🔒 28.0 MB 11.9 MB file 27.4 MB +622.1 KB (+2.3%) OK
✅ packed-program Linux 🔒 18.2 MB 7.5 MB file 17.7 MB +494.6 KB (+2.8%) OK
✅ baml-cli macOS 🔒 21.8 MB 10.4 MB file 21.3 MB +478.5 KB (+2.2%) OK
✅ packed-program macOS 🔒 14.2 MB 6.6 MB file 13.8 MB +376.6 KB (+2.7%) OK
✅ baml-cli Windows 🔒 23.4 MB 10.6 MB file 23.0 MB +478.1 KB (+2.1%) OK
✅ packed-program Windows 🔒 15.2 MB 6.7 MB file 14.8 MB +394.7 KB (+2.7%) OK
✅ bridge_wasm WASM 17.3 MB 🔒 4.7 MB gzip 4.6 MB +104.8 KB (+2.3%) 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

@antoniosarosi

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (7)
baml_language/crates/baml_tests/src/compiler2_tir/package_interface.rs (2)

1055-1070: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize the library blob across tests.

app_blob builds a fresh ProjectDatabase, loads every builtin stub, runs a full check, and derives the whole app interface. lib_blob() calls it once per test, and this module has 11 tests that use it. Each call repeats the same derivation over the identical LIB source. Cache the result in a LazyLock so the library compiles once per test binary.

♻️ Proposed memoization
     fn lib_blob() -> Vec<u8> {
-        app_blob(&[("lib.baml", LIB)])
+        static BLOB: std::sync::LazyLock<Vec<u8>> =
+            std::sync::LazyLock::new(|| app_blob(&[("lib.baml", LIB)]));
+        BLOB.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_tests/src/compiler2_tir/package_interface.rs`
around lines 1055 - 1070, Memoize the serialized library interface produced by
app_blob so the identical LIB fixture is compiled only once per test binary.
Introduce a LazyLock-backed cached blob and update lib_blob to return the cached
value, while preserving app_blob’s existing database construction and validation
behavior for callers that provide arbitrary files.

1098-1105: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert on the diagnostic code, not only on a substring of the message.

error_messages already formats each entry as [{code}] {message}. The current assertions match a bare identifier: "describe", "Retired", "Nope", "mounted". Any unrelated error that mentions the same identifier satisfies them. The missing-method test and the signature-mismatch test use the identical needle "describe", so they cannot distinguish E0113 from E0120, and either test would still pass if the checker instead emitted an unresolved-interface error. The test comments already name the intended codes. Add a code parameter and assert both.

♻️ Proposed helper change
     #[track_caller]
-    fn assert_error_containing(db: &ProjectDatabase, needle: &str) {
+    fn assert_error(db: &ProjectDatabase, code: &str, needle: &str) {
         let errors = error_messages(db);
         assert!(
-            errors.iter().any(|msg| msg.contains(needle)),
-            "expected an error containing {needle:?}, got:\n{errors:#?}"
+            errors
+                .iter()
+                .any(|msg| msg.starts_with(&format!("[{code}]")) && msg.contains(needle)),
+            "expected a {code} error containing {needle:?}, got:\n{errors:#?}"
         );
     }

Then pin each call site to its documented code, for example assert_error(&db, "E0113", "describe") at Line 1251, assert_error(&db, "E0120", "describe") at Line 1275, and assert_error(&db, "E0158", "mounted") at Line 1402.

🤖 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/src/compiler2_tir/package_interface.rs`
around lines 1098 - 1105, Update assert_error_containing to accept an expected
diagnostic code and assert that the formatted error contains both the code and
message needle. Change each call site to pass the code documented by its test,
including E0113 for the missing-method “describe” case, E0120 for the
signature-mismatch case, and E0158 for the “mounted” case, along with the
existing message needles.
baml_language/crates/baml_project/src/db.rs (1)

421-448: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Guard against a repeated path in add_compiler2_virtual_file.

Each call mints a new SourceFile input and pushes it onto Compiler2ExtraFiles. If a caller passes the same path twice, the database holds two inputs for that path and compiler2_all_files yields both. The result is duplicate item definitions and confusing diagnostics, not a clear error. add_or_update_file avoids this by checking the existing map first. Reuse the same shape here: if compiler2_file_map already contains the path, update its text and return the existing handle.

♻️ Proposed guard
     ) -> SourceFile {
         let path = path.as_ref().to_path_buf();
+        if let Some(&existing) = self.compiler2_file_map.get(&path) {
+            existing.set_text(self).to(content.to_string());
+            return existing;
+        }
         let file = self.add_file_internal(&path, content);
🤖 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_project/src/db.rs` around lines 421 - 448, Update
add_compiler2_virtual_file to check compiler2_file_map for the path before
creating a new SourceFile. When the path already exists, update the existing
handle’s text and return it without appending another entry to
Compiler2ExtraFiles; otherwise preserve the current creation and registration
flow.
baml_language/crates/baml_compiler2_hir/src/package.rs (1)

396-416: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit tests for the new mounted-package helpers.

mounted_package_names and is_mounted_package are now crate-visible helpers without in-crate tests. Add unit tests in package.rs::tests: empty mounted input, non-reserved mounted packages in deterministic order, reserved-name filtering, and is_mounted_package returning false for any reserved input.

🤖 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_hir/src/package.rs` around lines 396 -
416, Add unit tests in package.rs::tests covering empty mounted-package input,
deterministic ordering of non-reserved names from mounted_package_names,
filtering of reserved names, and false results from is_mounted_package for every
reserved input. Reuse the existing mounted-package and reserved-name test
helpers or fixtures, and also verify normal non-reserved membership behavior.

Source: Coding guidelines

baml_language/crates/baml_compiler2_tir/src/interfaces.rs (1)

1499-1527: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the requirement-match predicate shared with the source path.

The mounted block and the source closure walk at lines 1545-1556 apply the same four conditions: name equality, generic arity, pairwise generic equivalence, and sup associated-pin coverage. The two copies can drift when the matching rule changes.

Extract a helper that takes the realized requirement parts and sup, then call it from both sites.

♻️ Proposed shared predicate
fn requirement_matches(
    req_name: &QualifiedTypeName,
    req_generics: &[Ty],
    req_assoc: &[(Name, Ty)],
    sup: &baml_type::Interface,
    equivalent: &mut impl FnMut(&Ty, &Ty) -> bool,
) -> bool {
    req_name == &sup.name
        && req_generics.len() == sup.generics.len()
        && req_generics
            .iter()
            .zip(sup.generics.iter())
            .all(|(a, b)| equivalent(a, b))
        && sup.associated_types.iter().all(|(sup_name, sup_ty)| {
            req_assoc
                .iter()
                .find(|(name, _)| name == sup_name)
                .is_some_and(|(_, ty)| equivalent(ty, sup_ty))
        })
}
🤖 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 1499
- 1527, Extract a shared requirement_matches helper for the four matching
conditions: name equality, generic arity, pairwise generic equivalence, and sup
associated-type coverage. Replace the inline predicate in the mounted
ExportedType::Interface block and the corresponding source closure with calls to
this helper, passing each realized requirement’s name, generics, and associated
types while preserving the existing equivalent callback behavior.
baml_language/crates/baml_lsp2_actions/src/check.rs (1)

554-566: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the expect with a let-chain.

violation.secondary.expect("checked is_some above") re-reads a value that is_some_and just tested. A let-chain binds the span once and removes the panic path from the diagnostics surface.

♻️ Proposed refactor
         let (primary, secondary) = if violation.primary.file_id == file_id {
             (violation.primary, violation.secondary)
-        } else if violation
-            .secondary
-            .is_some_and(|span| span.file_id == file_id)
-        {
-            (
-                violation.secondary.expect("checked is_some above"),
-                Some(violation.primary),
-            )
+        } else if let Some(secondary) = violation.secondary
+            && secondary.file_id == file_id
+        {
+            (secondary, Some(violation.primary))
         } else {
             continue;
         };
🤖 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_lsp2_actions/src/check.rs` around lines 554 - 566,
Update the secondary-span branch in the violation filtering logic to bind the
matching value with a let-chain, replacing the separate is_some_and check and
violation.secondary.expect call. Preserve the existing file_id match and
primary/secondary ordering while eliminating the panic path.
baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs (1)

2386-2406: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Memoize package_impls.

package_impls reallocates its Vec<(ImplRef, &ImplData)> on every call. get_implements_block_within_depth enumerates packages at each recursion level while checking generic bounds, so the wrapper vector is rebuilt repeatedly on that path.

Make package_impls a tracked returns(ref) query so the impl list is reused from the same stable enumeration API.

🤖 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/impl_rules.rs` around
lines 2386 - 2406, Convert package_impls into a tracked returns(ref) query,
preserving its current package_impl_locs and mounted_impl_datas enumeration and
output ordering. Ensure callers such as get_implements_block_within_depth reuse
the memoized reference-backed result instead of rebuilding the wrapper Vec on
each call.
🤖 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/builder.rs`:
- Around line 945-952: Update check_function_parameter_defaults to take
foreign_callable_exprs out of the builder before checking defaults.exprs and
restore the original body-arena map afterward, matching the existing
save/restore handling for interface_method_generic_params,
owner_type_arg_binding_seed, self_pinned_rigid_var, and call_plans. Ensure
entries recorded for defaults ExprId values cannot remain visible during
function-body checking.

In `@baml_language/crates/baml_compiler2_tir/src/package_interface.rs`:
- Around line 1394-1402: Update the doc comment for ExportedType::Interface to
reflect current resolution: interface rows are consumed for mounted, source-less
dependencies, while remaining invisible for source-backed dependencies. Remove
the stale claim that resolution deliberately treats these rows as absent pending
a future dualized context, and align the wording with
resolve_type_in_own_then_deps and the nearby mounted-package gate.

---

Nitpick comments:
In `@baml_language/crates/baml_compiler2_hir/src/package.rs`:
- Around line 396-416: Add unit tests in package.rs::tests covering empty
mounted-package input, deterministic ordering of non-reserved names from
mounted_package_names, filtering of reserved names, and false results from
is_mounted_package for every reserved input. Reuse the existing mounted-package
and reserved-name test helpers or fixtures, and also verify normal non-reserved
membership behavior.

In `@baml_language/crates/baml_compiler2_tir/src/interfaces.rs`:
- Around line 1499-1527: Extract a shared requirement_matches helper for the
four matching conditions: name equality, generic arity, pairwise generic
equivalence, and sup associated-type coverage. Replace the inline predicate in
the mounted ExportedType::Interface block and the corresponding source closure
with calls to this helper, passing each realized requirement’s name, generics,
and associated types while preserving the existing equivalent callback behavior.

In `@baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs`:
- Around line 2386-2406: Convert package_impls into a tracked returns(ref)
query, preserving its current package_impl_locs and mounted_impl_datas
enumeration and output ordering. Ensure callers such as
get_implements_block_within_depth reuse the memoized reference-backed result
instead of rebuilding the wrapper Vec on each call.

In `@baml_language/crates/baml_lsp2_actions/src/check.rs`:
- Around line 554-566: Update the secondary-span branch in the violation
filtering logic to bind the matching value with a let-chain, replacing the
separate is_some_and check and violation.secondary.expect call. Preserve the
existing file_id match and primary/secondary ordering while eliminating the
panic path.

In `@baml_language/crates/baml_project/src/db.rs`:
- Around line 421-448: Update add_compiler2_virtual_file to check
compiler2_file_map for the path before creating a new SourceFile. When the path
already exists, update the existing handle’s text and return it without
appending another entry to Compiler2ExtraFiles; otherwise preserve the current
creation and registration flow.

In `@baml_language/crates/baml_tests/src/compiler2_tir/package_interface.rs`:
- Around line 1055-1070: Memoize the serialized library interface produced by
app_blob so the identical LIB fixture is compiled only once per test binary.
Introduce a LazyLock-backed cached blob and update lib_blob to return the cached
value, while preserving app_blob’s existing database construction and validation
behavior for callers that provide arbitrary files.
- Around line 1098-1105: Update assert_error_containing to accept an expected
diagnostic code and assert that the formatted error contains both the code and
message needle. Change each call site to pass the code documented by its test,
including E0113 for the missing-method “describe” case, E0120 for the
signature-mismatch case, and E0158 for the “mounted” case, along with the
existing message needles.
🪄 Autofix

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: 8c8cbf88-e9aa-4147-8a5d-25a00bb03feb

📥 Commits

Reviewing files that changed from the base of the PR and between 2891f48 and eb7d927.

📒 Files selected for processing (20)
  • baml_language/crates/baml_compiler2_hir/src/package.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/infer_context.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/lower_type_expr.rs
  • baml_language/crates/baml_compiler2_tir/src/package_interface.rs
  • baml_language/crates/baml_compiler2_tir/src/unify.rs
  • baml_language/crates/baml_compiler_diagnostics/src/diagnostic.rs
  • baml_language/crates/baml_lsp2_actions/src/check.rs
  • baml_language/crates/baml_project/src/db.rs
  • baml_language/crates/baml_surface/src/export.rs
  • baml_language/crates/baml_surface/src/handles.rs
  • baml_language/crates/baml_tests/src/compiler2_tir/package_interface.rs
  • baml_language/crates/baml_workspace/src/lib.rs

@antoniosarosi

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@vercel
vercel Bot temporarily deployed to Preview – beps August 6, 2026 06:27 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 August 6, 2026 06:35 Inactive
…, PR 4) (#4332)

**BEP-066 slice-6a stack, PR 4 of 5** — chained on #4329. Mounted-blob
packages become *callable*: TIR's loc-free `MemberResolution::External`
flows through MIR to B-693 unit symbols, and a two-DB compile-then-link
harness proves it end to end **at runtime**.

## What
- Loc-free call resolution for mounted packages: free functions, methods
on mounted classes, interface dispatch through blob impls (incl.
out-of-body and blanket impl methods), UFCS. PR 3's reserved E0158
shrinks to the genuine builtin-only residue (enumerated + tested).
- MIR lowers `External` callees to fq-name unit symbols; impl-method
`{iface}$for${target}` symbols reconstructed structurally with
source/blob agreement.
- Callback-effect framing (synthetic effect params) verified against
exported signatures.
- `$stream` policy landed + tested.
- **The two-DB link harness** — compile library → capture interface blob
→ fresh consumer DB mounting it → emit units from both → link → execute
— is the working prototype of slice 6's dynamic linking. 16/16 execution
tests: runtime call results asserted, mounted-class construction + field
reads, blob-impl dispatch, generic bounds via blob impls, cross-package
throws caught in user code.

## Gates
Focused suite 16/16 · tir + project + bytecode_cache green · full
baml_tests green · strict all-features clippy clean on every touched
crate · fmt clean · **zero snapshot churn**. (`--no-verify` only for the
known environmental mise/swift-protobuf hook failure; gates run
directly.)

Implemented by a Codex (gpt-5.6-sol) worker under stack-manager review.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for calling functions and methods from mounted,
precompiled packages.
* Enabled cross-package interfaces, generics, implementations, streaming
types, callbacks, and error handling.
* Added interface dispatch, class construction, UFCS calls, and
higher-order calls across package boundaries.
* Improved editor symbol classification and diagnostics for external
package symbols.

* **Bug Fixes**
* Restored mounted implementations and recursive type aliases when
rebuilding from a precompiled standard library.
  * Improved diagnostics for ambiguous interface field access.

* **Tests**
* Added comprehensive end-to-end coverage for mounted package
compilation, linking, and runtime execution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Antonio Sarosi <[email protected]>
@antoniosarosi
antoniosarosi merged commit 67d7fcc into antonio/s6a-impls-export Aug 7, 2026
4 of 7 checks passed
@antoniosarosi
antoniosarosi deleted the antonio/s6a-type-consumption branch August 7, 2026 05:30
@vercel
vercel Bot temporarily deployed to Preview – beps August 7, 2026 05:32 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 August 7, 2026 05:39 Inactive

This branch was previously deployed

2 inactive deployments
Preview – promptfiddle2 — bfaf1325 Deployed Aug 7, 2026 by vercel[bot]
Preview – beps — bfaf1325 Deployed Aug 7, 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