Skip to content

baml-language: Fix exhaustiveness alias expansion with cycle guard#3143

Open
miguelcsx wants to merge 3 commits intoBoundaryML:canaryfrom
miguelcsx:refac/enhaustiveness
Open

baml-language: Fix exhaustiveness alias expansion with cycle guard#3143
miguelcsx wants to merge 3 commits intoBoundaryML:canaryfrom
miguelcsx:refac/enhaustiveness

Conversation

@miguelcsx
Copy link
Contributor

@miguelcsx miguelcsx commented Feb 19, 2026

  • Adds a shared, cycle-safe alias expansion path for both scrutinee and pattern coverage.
  • Prevents infinite recursion on recursive or mutually recursive type aliases.
  • Aligns pattern coverage with scrutinee expansion to avoid false non-exhaustive reports.
  • Includes targeted unit tests for alias expansion and the regression case.

Summary by CodeRabbit

  • Improvements

    • Unified literal-to-value handling and a consolidated type-expansion path for more consistent pattern matching.
    • Robust type-alias expansion with cycle detection; better handling of enums, booleans, literals, lists, maps and class placeholders.
    • More accurate exhaustiveness and pattern-coverage logic with deduplication and reliable union/alias resolution.
  • Tests

    • Added comprehensive tests for alias expansion (transitive and cyclic), enums, unions, and coverage behavior.

@vercel
Copy link

vercel bot commented Feb 19, 2026

@miguelcsx is attempting to deploy a commit to the Boundary Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 19, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c3702f and e309576.

📒 Files selected for processing (1)
  • baml_language/crates/baml_compiler_tir/src/exhaustiveness.rs

📝 Walkthrough

Walkthrough

Adds cycle-guarded, recursive type-alias expansion and centralizes value-set generation by making ty_to_value_set an instance method, introducing expand_ty and values_into_value_set, converting literals to ValueSet, and updating pattern/coverage logic and tests accordingly.

Changes

Cohort / File(s) Summary
Exhaustiveness core
baml_language/crates/baml_compiler_tir/src/exhaustiveness.rs
Major rewrite: added expand_ty(&self, ty, visiting) with cycle guard; expand_type_to_values delegates to it; introduced ty_to_value_set(&self, ty) as instance method; implemented From<&LiteralValue> for ValueSet; added values_into_value_set(Vec<ValueSet>); updated type handling for TypeAlias, Enum, Bool, Null, Literal, List, Map, Class, and unknown/error cases.
Patterns & coverage logic
baml_language/crates/baml_compiler_tir/src/exhaustiveness.rs (pattern sections)
Pattern handling updated: Pattern::TypedBinding now uses ty_to_value_set on lowered types; Pattern::Union uses values_into_value_set to merge sub-pattern sets; coverage/check logic routed through the new expansion path and preserves catch-all/empty semantics.
Tests & scaffolding
baml_language/crates/baml_compiler_tir/tests/*
Extended tests to cover type-alias expansion scenarios: primitive aliases, bool, enum variants, transitive aliases, unions, cycles, aliased enums, and coverage validation for aliased enum scrutinees.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly describes the main fix: cycle-guarded exhaustiveness alias expansion for type aliases, matching the core objective of preventing infinite recursion and aligning pattern coverage with scrutinee expansion.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

@miguelcsx miguelcsx force-pushed the refac/enhaustiveness branch from c64df80 to ecf3b56 Compare February 19, 2026 23:33
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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/baml_compiler_tir/src/exhaustiveness.rs (1)

258-270: 🧹 Nitpick | 🔵 Trivial

Misleading comment in ValueSet::Empty branch of check().

The comment on line 264 says "Guarded patterns don't contribute", but guarded patterns never reach this branch: pattern_to_value_set already returns ValueSet::Empty for guarded arms (via the early return at the top of pattern_to_value_set), and the surrounding if !has_guard at line 258 is a second gate. The Empty here originates from void/error-typed patterns.

🧹 Suggested clarification
-                ValueSet::Empty => {
-                    // Guarded patterns don't contribute
-                }
+                ValueSet::Empty => {
+                    // void/error-typed patterns produce no values and don't contribute
+                }

@aaronvg
Copy link
Contributor

aaronvg commented Feb 20, 2026

Thanks for the PR! were you testing out the compiler? or what prompted you to tackle this?

@miguelcsx
Copy link
Contributor Author

miguelcsx commented Feb 20, 2026

Thanks for the PR! were you testing out the compiler? or what prompted you to tackle this?

Hi @aaronvg, I was trying out the new compiler and noticed the exhaustiveness checker was missing a cycle guard for recursive type aliases (there was a TODO about it).

While addressing that, I discovered typed patterns weren’t expanding through aliases during coverage checks, which caused valid matches to be reported as non-exhaustive.

@rossirpaulo
Copy link
Contributor

Thanks for the PR! were you testing out the compiler? or what prompted you to tackle this?

Hi @aaronvg, I was trying out the new compiler and noticed the exhaustiveness checker was missing a cycle guard for recursive type aliases (there was a TODO about it).

While addressing that, I discovered typed patterns weren’t expanding through aliases during coverage checks, which caused valid matches to be reported as non-exhaustive.

yep, i just checked it out. i really appreciate your help with that todo! i'll do some final tests before merging.

that said, i'm curious to learn what sparked your interest in trying out baml. have you joined our discord yet? i'm happy to get your thoughts about what we're building :)

@miguelcsx
Copy link
Contributor Author

Hey @rossirpaulo, thanks. I got into BAML while experimenting in a small project and trying to understand how the compiler and runtime fit together.

I’m planning to keep exploring other parts of the repo and sending small fixes when I run into issues.

If there’s an area that would benefit most from extra eyes right now, I’d be happy to focus there.

@miguelcsx miguelcsx force-pushed the refac/enhaustiveness branch from 09ec039 to 3c3702f Compare February 28, 2026 20:08
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecf3b56 and 3c3702f.

📒 Files selected for processing (1)
  • baml_language/crates/baml_compiler_tir/src/exhaustiveness.rs

- collapse ValueSet unions containing All to a single catch-all

- keep Empty filtering semantics intact
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.

3 participants