Delete old TIR type algebra - #4032
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (3)
📝 WalkthroughWalkthroughThe compiler adds alias-aware structural equivalence, migrates TIR and MIR matching logic to use it, narrows TIR normalization to cycle detection, and adds tests for recursive aliases and function subtyping rules. ChangesType equivalence and cycle detection
Estimated code review effort: 4 (Complex) | ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
⏭️ Performance benchmarks were skippedPerf benchmarks (CodSpeed) are opt-in on pull requests — they no longer run on every push. They always run automatically after merge to To run them on this PR, do any of the following, then push a commit (or re-run CI):
|
Also added versions of some of its tests to the `baml_type` normalization tests
51f15dc to
02eaaf5
Compare
Binary size checks passed✅ 7 passed
Generated by |
…rness (BoundaryML#4038) ## Summary - Adds `baml_language/crates/tools_compile_profile`, a standalone black-box profiling harness for the compiler pipeline (parse → HIR → PPIR → TIR → MIR → emit). It reports wall-clock per phase, per-Salsa-query execution / cache-hit / blocked counts, cold-run variance, cold-vs-warm comparison (`--warm-runs`), and JSON output. - Ported verbatim from PR BoundaryML#4016 (`perf/compiler2-cold-compile`), with two adaptations: the `PROF_*` TIR audit counters (which only existed on that branch) are removed rather than ported, and the "July 2026 cold-compile audit" README section is annotated as a historical record predating BoundaryML#4032 / BoundaryML#3924. - Workspace changes: `mimalloc = "0.1.52"` added to workspace deps (used only by this tool, as its global allocator — noted in the README), and `"compile"` added to the `tools` namespace `approved_prefixes` in `stow.toml`. Provenance: BoundaryML#4016. The remaining findings from that audit are being re-landed as small independent PRs measured with this tool. ## Baseline on current canary (2660b8b) Protocol: `cargo build --release -p tools_compile_profile`, then `./target/release/tools_compile_profile baml_language/crates/baml_tests/baml_src --repeat 5` with `BAML_NO_BYTECODE_CACHE=1` and `BAML_CACHE_DIR` pointed at a fresh temp dir (so BoundaryML#3924's disk cache is out of the picture). Corpus: 77 files, 25,212 lines. Apple Silicon, single-threaded, medians of 5 cold runs. | phase | median | |---|---| | check | 1.089 s | | emit (bytecode) | 1.330 s | | **total** | **2.420 s** (min 2.385, mean 2.442, max 2.524) | For comparison, BoundaryML#4016's pre-optimization baseline on this corpus was 16.0s and its final state ~0.50s. Canary's own movement (BoundaryML#4032 deleting the old TIR type algebra, BoundaryML#3924's caching work) already brought cold compile from 16.0s to ~2.4s; the still-orthogonal optimizations from BoundaryML#4016 target the remainder. ### Top 10 queries by executions (cold, representative run) | exec | query | |---|---| | 15,590 | `infer_scope_types` | | 2,262 | `function_in_scope_generic_param_bounds` | | 2,256 | `function_body` | | 2,131 | `callable_throws` | | 625 | `class_generic_param_bounds` | | 477 | `resolve_class_fields` | | 419 | `function_parameter_defaults` | | 419 | `function_signature` | | 147 | `impl_data` | | 147 | `impl_data_source_map` | 25,972 total query executions; TIR is 18,697 of them (72%). ## Test plan - [x] `cargo build --release -p tools_compile_profile` clean - [x] Clean run against `baml_language/crates/baml_tests/baml_src` (`--repeat 5`) - [x] Pre-commit hooks: cargo fmt, workspace clippy (`-D warnings`), cargo stow, markdown validation Made with [Cursor](https://cursor.com) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced a standalone compiler profiling harness to measure compilation phase timings and query execution/caching behavior, including cold vs warm runs. * Generates human-readable and JSON reports, with optional compact summary output and validation-only mode. * **Documentation** * Added comprehensive documentation covering CLI usage, report interpretation, flamegraph pairing guidance, and profiling methodology. * **Tests** * Added tests for query-to-phase mapping and report-related behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
…ns (2.4s → 0.81s cold) (BoundaryML#4058) Re-lands the still-orthogonal cold-compile optimizations from BoundaryML#4016, re-derived from scratch against current `canary` (which moved underneath BoundaryML#4016 via BoundaryML#4032 and BoundaryML#3924). Not a rebase of BoundaryML#4016 — every change was re-derived and re-measured. BoundaryML#4016's single biggest win (recursive-alias hoist) is intentionally **not** here: BoundaryML#4032 already captured it by deleting the old TIR `StructuralTy` algebra. The profiler itself already landed separately as BoundaryML#4038. ## Measurement Corpus: `crates/baml_tests/baml_src` (77 files, 25,212 lines). Protocol: `tools_compile_profile ... --repeat 5`, disk cache disabled (`BAML_NO_BYTECODE_CACHE=1`, fresh `BAML_CACHE_DIR`). Cold-cache medians of 5 runs, single-threaded. | | check | emit | **total** | |---|---|---|---| | canary (`8c29c827e`) | 1.114 s | 1.277 s | **2.392 s** (min 2.354 / max 2.537) | | this branch | 0.462 s | 0.345 s | **0.808 s** (min 0.791 / max 0.828) | **3.0x faster** cold check+emit, single-threaded. (For reference, the pre-BoundaryML#4032 baseline this work originally started from was ~16 s; BoundaryML#4032 alone brought cold compile to a few seconds, and this branch takes it under ~1 s.) Key query-count deltas (cold, corpus): `infer_scope_types` 15,590 → **13,331** (PPIR→HIR `file_semantic_index` delegation removes duplicate scope inference); `package_resolved_aliases` / `package_impl_locs` no longer rebuilt inside every one of those inference calls (now a handful of per-package executions); new memoized queries `file_ast` (131, once/file), `callee_generics_for_func` (1,834), tracked PPIR `function_body`. ## What's in it (one commit per track) - **`file_ast` tracked query** — lower CST→AST once per file (items + lowering diagnostics + env refs), shared by both `file_semantic_index` queries, `ppir_expansion_items`, the project-wide expansion collectors, and the LSP check path; PPIR `file_semantic_index` delegates to HIR's when a file has no `$stream` expansions; PPIR `function_body` tracked. - **package-level TIR queries** — `package_resolved_aliases` (+ `cycle_initial` seeding an empty env, mirroring `infer_scope_types` — it sits in a real salsa cycle via associated-type-projection alias RHS) and `package_impl_locs` as tracked queries, plus `callee_generics_for_func`, so the alias map / impl-block list / callee generics stop being rebuilt per inference call. - **nested-lambda inference projection** — lambda bodies were inferred twice (inline in the owner scope, then again by the standalone `ScopeKind::Lambda` query), which also emitted duplicate diagnostics inside lambdas. The inline pass now captures the lambda's tables and the Lambda arm projects them; synthetic desugared `test`/`testset` bodies fall through to standalone inference so their diagnostics are still emitted. Snapshot updates where the duplicate lambda diagnostics disappear are the point. - **MIR dispatch prefilter + subtype fast paths** — `dispatch_target_for_concrete` gates its per-call impl enumeration behind a package-wide `FxHashSet` of interface-declared method names (own package + dependency closure); `baml_type::normalize` gets a reflexivity + `heads_definitely_differ` fast-reject in `equivalent()` (conservative: same-kind nominal pairs only — List/EvolvingList collapse to the same canonical head post-BoundaryML#4032) and restricts `is_subtype_of` co-inductive assumption bookkeeping to the expanding arms (Mu / TypeVar / AssociatedTypeProjection) via `is_subtype_of_inner`, with a termination argument in-comment. Re-derived onto the post-BoundaryML#4032 `baml_type` algebra (the only equivalence path now). - **memoized `class_type_tags_for_project`** — the project-wide class → type-tag map was rebuilt (every file's item tree walked, every class name re-rendered and re-hashed) inside every `LoweringContext` construction, i.e. once per lowered function (~420x on the corpus; the hottest MIR frame in a CPU sample). Now a `#[salsa::tracked]` query keyed on the `Project` input; `LoweringContext` borrows it. This is BoundaryML#4016 audit item BoundaryML#4, initially assumed superseded by BoundaryML#3924's content-addressed tags — BoundaryML#3924 changed the tag *values* but left the per-function rebuild in place. Also adds this PR chain's new tracked queries to the profiler's `phase_for_query` table. - **match usefulness report reuse + emit buffer pre-sizing** — match checking ran the full usefulness matrix twice per `match` (exhaustiveness, then an identical second pass for unreachable-arm detection whenever no arm had a pattern error); the reachability pass now reuses the exhaustiveness report (exhaustiveness: ~11% -> ~1.7% of CPU inclusive). `StackifyCodegen` pre-sizes its bytecode/meta buffers and local/block maps from the MIR's shape instead of growing from empty per function. - **CLI mimalloc + diagnostic rendering** — mimalloc as `baml_cli`'s global allocator; build the ariadne `SourceCache` once per diagnostic batch instead of once per diagnostic. Verified byte-for-byte identical rendered diagnostics and clean `BAML_CACHE_VERIFY=1` (so BoundaryML#3924's cached-diagnostic replay does not diverge). ## Deliberately not re-landed - The BoundaryML#4016 recursive-alias hoist — superseded by BoundaryML#4032. - Skip-builtin-diagnostics — superseded by BoundaryML#3924's per-toolchain builtin-diagnostics cache. ## Testing Full workspace test suite green except two pre-existing/environmental failures unrelated to this change: a Python cancellation pytest that fails identically on clean `canary` (local Python < 3.11: `ExceptionGroup`/`CancelledError.reason`). `cargo fmt` + `clippy -D warnings` clean. Provenance: BoundaryML#4016 (reference implementation, kept as reference, not merged). 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This migrates the remaining users of the old TIR
StructuralTy-based type algebra logic to use the canonicalbaml_typealgebra. It also provides a major performance improvement by avoiding the costly recursive alias checker in the hot path: compiling thebaml_tests/baml_srcsuite is now several times faster on my laptop.Summary by CodeRabbit
Bug Fixes
ArrayandMap(key/value/element types now require equivalence).Tests