Skip to content

feat(tir): export the impls table on PackageInterface (BEP-066 slice 6a, PR 2) - #4327

Merged
antoniosarosi merged 2 commits into
antonio/s6a-export-schemafrom
antonio/s6a-impls-export
Aug 7, 2026
Merged

antoniosarosi merged 2 commits into
antonio/s6a-export-schemafrom
antonio/s6a-impls-export

Conversation

@antoniosarosi

@antoniosarosi antoniosarosi commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

BEP-066 slice-6a stack, PR 2 of 5 — chained on #4326. Derivation only, zero behavior change (impls is written, never read; consumers land in PR 3/4).

What

PackageInterface.impls: Vec<ExportedImpl> — everything a source-less consumer needs for impl matching and conformance without ImplLocs: interface head (args + realized assoc bindings), for_ty_pattern as Ty over the impl's rigid ParamTys, generic params + bounds, assoc rows in declaration order, field links, origin (doc-carried as diagnostic-metadata-only), and per-method rows with structural identity (owner = the row's interface+for-ty pair; MIR's source-text-derived {iface}$for${target} naming deliberately not replicated — the consumer PR reconstructs it structurally).

Key choices

  • Impl-method signatures lower exactly as validate_impl_signatures lowers the impl side (InterfaceMethodSpec spine + realize_with_symbolic_self, Self → for_ty substituted last) — NOT function_signature_ty, which lowers free-impl methods without a Self binding (its own documented deficiency).
  • Ordering: rows sort by their borsh encoding — canonical, file-order-independent.
  • Malformed impls: skipped exactly as existing consumers filter ImplDataError; diagnostics stay owned by impl_data.
  • No spans (Salsa span-free rule): verified coherence needs none structurally — dep-side attribution renders structurally; noted for the consumer PR.

Proof

  • tir: 324 ✓ · full baml_tests: 2511 ✓, zero snapshot churn · bytecode_cache (B-694): 43 ✓ · new impl suite: 8 tests incl. generic-impl bounds, assoc pins + filled defaults, blanket impl, and the stdlib implement Equals for int spot-check (other: Self → int).
  • Only non-tir change: realize_with_symbolic_self visibility (pub(crate)) + a test-sentinel literal.

Summary by CodeRabbit

  • New Features

    • Package interfaces now export comprehensive implementation metadata, including interface relationships, generics, associated types, field links, origins, and method signatures.
    • Exported implementation data is serialized consistently and included when packages are combined.
  • Bug Fixes

    • Improved handling of implementation metadata across in-body, out-of-body, generic, and standard-library implementations.
  • Tests

    • Added extensive coverage for implementation exports, type resolution, associated types, method metadata, serialization, completeness, and deterministic output.

…6a, PR 2)

Add PackageInterface.impls: Vec<ExportedImpl> — the loc-free blob-side
twin of the impl_data substrate, so a source-less dependency can later
contribute its impls to matching, membership, and coherence (the R2
fails-open hole). Derivation only: nothing reads the new rows, the
ImplLoc enumerators are untouched, and diagnostics/bytecode stay
byte-identical (full baml_tests suite green, snapshots unchanged).

Schema (package_interface.rs):
- ExportedImpl { interface, for_ty_pattern, generic_params,
  param_bounds, associated_types, field_links, origin, methods }.
  Patterns are Ty over the impl's rigid ParamTy TypeVars (the currency
  match_ty_patterns keys on — deliberately not TyTemplate); the
  interface head carries args + realized assoc bindings (explicit pins
  plus filled defaults), canonicalized by Interface::new's by-name sort.
- ExportedImplOrigin mirrors InterfaceImplOrigin (diagnostic metadata
  ONLY — must not drive resolution/dispatch/coherence).
- ExportedImplMethod { name, sig }: a STRUCTURAL identity — the owner is
  the enclosing row (interface head + for-ty) — never MIR's
  {iface}$for${target} source-text naming, which the consumer PR
  reconstructs from the pair. No spans anywhere (Salsa span-free rule).

Derivation (fold_package_interface -> exported_impls): enumerate
package_impl_locs, read impl_data verbatim; malformed impls
(Err(ImplDataError)) are skipped exactly as every resolution consumer
skips them — their diagnostics stay owned by impl_data/check.rs. Rows
sort by their borsh encoding: a canonical total order independent of
file enumeration order (two-database determinism).

Method signatures lower exactly as the conformance checker lowers the
override side (validate_impl_signatures): impl + method generics in
scope, method bounds joining the bounds map (the
resolve_interface_method_spec shape), and Self realized through
realize_with_symbolic_self (now pub(crate)) — rigid Self bounded by the
implemented interface, Self -> for_ty_pattern substituted last — NOT
function_signature_ty, which lowers free-impl methods without a Self
binding (Ty::Error mentions). Throws pairs the declared clause with the
callable_throws oracle, as every exported function does.

Tests (baml_tests compiler2_tir::package_interface): in-body impl with
field links + override rows, out-of-body impl realizing Self in
receiver/param/return positions, generic bounded impl
(implement<T extends Anchor> Pair<T,T> for Box<T>), assoc pins + filled
Self.Item[] default staying a symbolic projection on the receiver,
blanket implement<T> I for T, stdlib spot-check
(baml.ops implement Equals for int), borsh round-trip and two-database
determinism now covering impls. B-694 bytecode_cache suites stay green
(sentinel literal gains the new field).
@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:38am
promptfiddle2 Ready Ready Preview Aug 7, 2026 5:38am

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: c3ecbcbf-ac32-43fe-b1e7-d5f8975488fb

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

The package interface now exports canonical, Borsh-serializable implementation rows with resolved types, bounds, associated types, field links, origins, and method metadata. Lowering realizes symbolic Self, and tests cover implementations, stdlib derivation, determinism, and round trips.

Changes

Package implementation exports

Layer / File(s) Summary
Exported implementation contract
baml_language/crates/baml_compiler2_tir/src/package_interface.rs
PackageInterface now includes serializable implementation rows, origins, method overrides, bounds, associated types, and field links.
Implementation row lowering
baml_language/crates/baml_compiler2_tir/src/interfaces/impl_rules.rs, baml_language/crates/baml_compiler2_tir/src/package_interface.rs
Package folding lowers resolvable implementations, realizes symbolic Self, preserves method metadata, sorts rows deterministically, and stores them in PackageInterface.
Implementation export validation
baml_language/crates/baml_tests/src/compiler2_tir/package_interface.rs, baml_language/crates/baml_cli/src/bytecode_cache.rs
Tests cover implementation origins, generics, associated types, blanket implementations, stdlib implementations, method metadata, Borsh round trips, and updated sentinel construction.

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

Sequence Diagram(s)

sequenceDiagram
  participant PackageFolding
  participant InterfaceResolution
  participant PackageInterface
  PackageFolding->>InterfaceResolution: Read implementation locations and data
  InterfaceResolution->>PackageInterface: Lower implementation rows and methods
  PackageInterface->>PackageInterface: Sort rows by Borsh encoding
  PackageInterface-->>PackageFolding: Return folded package interface
Loading

Possibly related PRs

Suggested reviewers: 2kai2kai2, hellovai, codeshaunted

Poem

I’m a rabbit with rows in a neat little line,
Borsh keeps each impl export fine.
Self finds its shape, bounds settle in place,
Methods and links now leave a clear trace.
Hop, test, round-trip—the package is bright!

🚥 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 identifies the main change: exporting the impls table on PackageInterface as part of the TIR BEP-066 work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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-impls-export

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 00:04 Inactive
@vercel
vercel Bot temporarily deployed to Preview – promptfiddle2 August 6, 2026 00:11 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.

…lice 6a, PR 3) (#4329)

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

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## 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.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Antonio Sarosi <[email protected]>
@antoniosarosi
antoniosarosi merged commit 1af00a9 into antonio/s6a-export-schema Aug 7, 2026
4 of 7 checks passed
@antoniosarosi
antoniosarosi deleted the antonio/s6a-impls-export branch August 7, 2026 05:31
@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:38 Inactive

This branch was previously deployed

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