Avatar for the BoundaryML user
BoundaryML
baml
BlogDocsChangelog

Performance History

Latest Results

Fix interface `Self` bugs (#3647) - `Self` should behave like a pinned type variable, not an dyn-interface-type. Makes this (correctly) produce a compiler error: ```baml interface Equatable { function eq(self, other: Self) -> bool } function cmp<S extends Equatable, U extends Equatable>(x: S, y: U) -> bool { return x.eq(y) } ``` - Limits interface implementations to only concrete types. You cannot do `implement Foo for int | string`. This prohibition applies to all abstract types: unions, optionals, interfaces, `unknown` - Fixes to bounds across typevars <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * BEP-044: Self-pinned support for interface default methods; interface-method values now dispatch to concrete implementors at runtime. * **Diagnostics** * New validation rejecting non-concrete `implements ... for ...` targets (error E0138). * **Tests** * Added compile-time and runtime tests for Self-pinned default methods, associated-type behavior, generic-bound soundness, and `implements ... for ...` constraints. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
canary
28 minutes ago
fix: thread inferred generic type args through interface dispatch (#3667) ## Problem A generic class instance whose `<T>` is **inferred** (not written explicitly) must carry the correct runtime `class_type_args`, and a method dispatched through a multi-implementor interface must receive the resolved class/interface type args in its frame. The interface-dispatch switch (`emit_method_candidate_switch`) called the matched implementor's method with **only the explicit call-site `<...>` type args** — it never seeded the callee frame. So an interface **default method** (e.g. a lazy iterator's `map` building `Map<T, U>`), or any dispatched method that reads its enclosing `T` at runtime (`reflect.type_of<T>()`, constructing `Other<T>{}`), saw an empty `frame.type_args`. It then built instances with `class_type_args = [unknown]`, and the downstream `IsType` dispatch guard fell through to the **wrong implementor** — a silent wrong answer, or a field-access panic when the sibling class has a different layout. This was the core compiler blocker for the `baml.iter` lazy-iterator protocol. ### Minimal reproduction (before this fix) ```baml interface Cursor<T> { function head(self) -> T throws unknown // default method builds a NEW generic from the interface's T function take_one(self) -> Cursor<T> throws unknown { return SingleCursor<T> { value: self.head() } } } class ArrayCursor<T> { arr T[] idx int function of(items: T[]) -> ArrayCursor<T> { return ArrayCursor<T> { arr: items, idx: 0 } } implements Cursor<T> { function head(self) -> T throws unknown { return self.arr[0] } } } class SingleCursor<T> { value T implements Cursor<T> { function head(self) -> T throws unknown { return self.value } } } function take_one_then_head() -> int throws unknown { let cursor: Cursor<int> = ArrayCursor.of([10, 20, 30]); // <int> inferred let single: Cursor<int> = cursor.take_one(); // builds SingleCursor<?> single.head() // expected 10 } ``` Before: `take_one()` (a default method) had empty `frame.type_args`, so `SingleCursor<T>` was built with `class_type_args = [unknown]`. `single.head()` then failed the `SingleCursor<int>` guard and dispatched to `ArrayCursor.head`, which indexed a non-existent `arr` field. After: returns `10`. ## Fix (in `baml_compiler2_mir::lower`) 1. **`enclosing_generic_params()`** now includes the **interface's** generic params for interface default methods. They are lowered as standalone functions whose bodies reference the interface's `T`; without this, `TypeVar(T)` lowered to `Concrete(Void)` instead of `TypeArgRef(N)`. 2. **The interface-dispatch switch** seeds each candidate's callee frame (De Bruijn order: class/iface params first, then explicit call-site args): - a **class-owned** method gets the implementor's class args — **statically** when the guard fully pins them (common/hot path, allocation-free, unchanged bytecode), otherwise from the **matched runtime instance** via a `BoundMethod` (covers `Any`/partial guards, e.g. a generic class behind a *non-generic* interface); - an **inherited interface default** gets the resolved interface view's args (these can differ from the implementor's class args when the `implements` block renames/reorders params). 3. **`default.<method>()`** (the super-like form that forwards into the interface default) seeds the default frame with the interface's type args too. ## Tests New in-BAML regression namespace `crates/baml_tests/baml_src/ns_inferred_generic_type_args`: - `showcase_lazy_cursor_pipeline` — the lazy-cursor example above, end-to-end. - `inferred_static_ctor_dispatches_to_correct_implementor` — inferred static ctor + non-generic interface. - `inferred_static_ctor_dispatches_through_generic_interface` — inferred static ctor + generic interface, mismatched field shapes. - `interface_default_method_sees_interface_type_var` — default method reads `T` via `reflect.type_of<T>()` at runtime. - `class_method_builds_generic_via_class_type_var` — class-owned method builds a generic from its class `T`. - `default_method_forward_reads_interface_type_var` — `default.<method>()` forwarding into a generic default. - `generic_class_behind_nongeneric_interface_reads_type_var` — `Any`-guard case, seeded from the runtime instance. Full `baml_tests` suite green. Existing bytecode snapshots unchanged — only the new namespace's `.snap` changed (no existing namespace exercised this path; the `BoundMethod` path fires only for previously-broken `Any`/partial-guard generic arms). ## Known limitation (separate, pre-existing — not addressed here) A generic class whose **only** field is `T[]`, built via a static constructor with inferred `T`, gets wrong `class_type_args` from the *producer* side (a TIR inference issue in the struct literal, independent of this dispatch fix). Adding any second field (as every real iterator has, e.g. `idx: int`) avoids it, so it does not affect the `ArrayIterator`-shaped use case. Worth a separate investigation. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed generic type-argument propagation for interface dispatch so dispatched calls—including default-method forwards and class-owned implementations—receive correct runtime type arguments. * **Tests** * Added end-to-end tests validating inferred generic type args flow through interface dispatch, default-method forwarding, class-owned vs instance-seeded cases, and regressions for varied implementor layouts. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
canary
2 hours ago
[codex] Implement BEP-57 associated types (#3652) ## Summary Implements BEP-57 associated types for interfaces across parsing, AST/HIR/TIR/MIR, formatter, LSP diagnostics, and codegen-facing surfaces. Key pieces: - Adds associated type declarations, defaults, bounds, and body-side witnesses in `implements` blocks. - Supports associated type bindings on interface value types and generic bounds. - Adds associated type projection syntax, including qualified `(Type as Interface<...>).Member` disambiguation. - Keeps `.as<T>` as upcast-equivalent while enforcing associated binding compatibility. - Rejects target-side witnesses like `implements Iterator<Item = int>`; witnesses must be declared inside the block (`type Item = int`) Rust/Swift-style. - Covers union, match/destructure narrowing, ambiguity, aliases, diagnostics, formatter, and runtime dispatch cases. ## Root Cause / Design Notes The parser can recognize `Iterator<Item = int>` as a type expression, but BEP-57 semantics reserve associated type witnesses for the body of an implementation. The implementation therefore preserves interface type bindings for values/bounds/projections while rejecting bindings on `implements` targets. ## Validation - `cargo fmt` - `cargo check -p baml_compiler2_tir -p baml_compiler2_mir -p baml_lsp2_actions -p baml_compiler2_ast -p baml_compiler_parser -p baml_fmt` - `cargo build -p baml_cli` - `cargo test -p baml_tests --test interfaces_associated_types -- --nocapture` (93 passed) - `cargo test -p baml_tests --test interfaces -- --nocapture` (379 passed, 2 ignored) - `cargo test -p baml_tests` (full package passed) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Large, cross-cutting compiler and runtime changes to interface typing, dispatch, and reflection; incorrect binding matching could cause subtle dispatch or pattern-match bugs. > > **Overview** > Adds **BEP-057 associated types** end-to-end: interfaces can declare associated types (bounds/defaults), and `implements` blocks can witness them with `type Name = …` instead of putting bindings on the `implements` target. > > The AST/HIR layer gains **`AssociatedTypeBinding`**, **`associated_type_bindings` on `TypeExpr::Path`**, **`AssociatedTypeProjection`** (`Base.Item` / `(Base as Interface).Item`), and matching fields on interfaces, `implements` blocks, class destructuring, and method-to-interface metadata. Lowering wires CST `TYPE_ARGS` / associated decls through `lower_type_expr` and `lower_cst`. > > **MIR and emit** stop erasing interfaces to classes: `Ty::Interface` keeps type args plus associated bindings; interface dispatch, field access, pattern matching, `is`-type tests, and the runtime **implementor registry** all compare **generic args and associated bindings** (e.g. `Source<Item = int>` vs `Item = string`). Builtin codegen treats projections as unknown types for native extraction. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cecf4f4bfcbebb130d0039392420d76f49091a95. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added associated types on interfaces (BEP-057): syntax, projections, named bindings; type checking, dispatch, pattern matching, and exhaustiveness honor associated bindings. * **Tests** * Extensive new and updated unit/integration tests covering parsing, lowering, inference, matching, dispatch, and runtime behavior for associated types. * **Tooling** * Parser, formatter, LSP symbols, diagnostics, snapshots, and pretty-printers updated to recognize and display associated-type syntax and errors. * **Runtime & Serialization** * Runtime reflection, serialization, FFI wire formats, and program metadata now include associated-bindings. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
canary
6 hours ago
Overhaul BAML language release pipeline (#3639) ## Summary Overhauls the BAML language release path around the new wrapper/toolchain split. - adds the `baml` wrapper crate plus shared `baml_release` and stamped `baml_version` crates - replaces the alpha release workflows with a channel-aware release graph, PyPI publish workflow, dry-run manifests, and wrapper-only Homebrew/AUR publishing paths - moves language/toolchain version authority to `baml_language/release.toml` and `scripts/baml-language-version` - makes the VSIX platform-neutral, launches `baml lsp` through the wrapper, and adds LSP/playground compatibility metadata - adds curl/PowerShell installers, package-manager artifact generation scripts, and in-repo docs for install/release/toolchain behavior ## Validation - pre-commit hooks passed, including: - `cargo fmt` - `cargo stow` - `cargo clippy --workspace --all-targets --all-features -- -D warnings` - YAML checks - `actionlint .github/workflows/release-baml-language.yml .github/workflows/publish-python-pypi.yml .github/workflows/build-python-sdk.reusable.yaml` - `cargo check --manifest-path baml_language/Cargo.toml -p baml -p baml_release -p baml_cli` - `cargo test --manifest-path baml_language/Cargo.toml -p baml_release` - `scripts/baml-language-version check` - `scripts/baml-wrapper-version check` - `typescript2/app-vscode-ext`: `./node_modules/.bin/tsc --noEmit` ## Release Follow-ups Before enabling production publishes: - update or validate the PyPI trusted publisher binding for `.github/workflows/publish-python-pypi.yml` - verify `scripts/install.ps1` on Windows/PowerShell - confirm production GitHub Actions secrets/OIDC paths for PyPI, AWS, Homebrew, and AUR - review whether the included `TASK/*` planning files should remain in the branch <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * New standalone baml wrapper/launcher with toolchain commands, self-update, IDE VSIX installer, per-project VS Code clients, and protocol/handshake compatibility. * **Installers & Packaging** * POSIX and Windows installers; Homebrew/AUR formula and packaging artifact generators; packaging adjusted to ship the wrapper binary. * **Documentation** * Expanded install, toolchain, release, maintainer, failure-modes, command-surface, migration, and merge-to-canary guides. * **CI / Releases** * Channel-aware release pipelines, release-plan stamping/manifest generation, reusable workflow inputs added, legacy alpha workflows removed; SDKs bumped to 0.11.0. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
canary
7 hours ago

Latest Branches

CodSpeed Performance Gauge
N/A
ci(perf): opt-in perf on PRs, run after merge, adaptive bench sampling#3651
22 hours ago
9ff494e
hellovai/perf-fixes
CodSpeed Performance Gauge
+1%
ci: R2-backed cache-cargo-home action for cargo download caches#3624
3 days ago
8300850
sam/cache-cargo-home
CodSpeed Performance Gauge
0%
© 2026 CodSpeed Technology
Home Terms Privacy Docs