-
Notifications
You must be signed in to change notification settings - Fork 349
Match Exhaustiveness Checking #2838
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: paulo/match
Are you sure you want to change the base?
Conversation
…mitives, named types, optional types, list types, union types, and string literal types. Refactor `lower_type_ref` and add `lower_type_text` for improved match exhaustiveness.
…g support for boolean and integer literal types.
…and more This commit introduces functions to build type alias and enum variant definitions from a project, enhancing the exhaustiveness checking capabilities. The `TypeContext` struct is updated to store these definitions, and the `infer_function` and `check_match_exhaustiveness` functions are modified to utilize this new information for improved match coverage analysis.
… `from_type_text` to handle boolean and integer literal types
…rove comments for clarity on string and integer literal types.
…nd `generate_diagnostics_test` functions.
…enhancing exhaustiveness checking in type lowering.
…rate it into `Ty` for singleton type support.
…aliases and enum variants
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
… in singleton types
CodSpeed Performance ReportMerging #2838 will not alter performanceComparing Summary
Footnotes
|
…o check for zero-variant enums in exhaustiveness checking.
antoniosarosi
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work! All my review is in comments referencing source code. Overall great PR, needs some AI cleaning, additional tests, and other less important nits.
| else if let Ok(int_val) = text.parse::<i64>() { | ||
| TypeRef::IntLiteral(int_val) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to check for numbers that are greater than i64::MAX and issue diagnostics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added a comment and TODO here so we can address this at a later time.
For anyone else in the team reading, find more context here: https://magnaplay.slack.com/archives/C0A3P816B0W/p1766183421615089
baml_language/crates/baml_tests/projects/match_exhaustiveness/match_exhaustiveness.baml
Show resolved
Hide resolved
.../baml_tests/snapshots/match_exhaustiveness/baml_tests__match_exhaustiveness__06_codegen.snap
Show resolved
Hide resolved
…e context in code generation
- Add is_union() and parts() methods to TypeExpr in ast.rs - Simplify TypeRef::from_ast() to use new accessors - Remove duplicate lower_type_ref() from lib.rs and signature.rs - Fix: primitives now recognized inside type constructors (int? → Optional(Int))
- Add unit tests for from_type_text covering "literal"?, "literal"[], and nested combinations like "literal"[]? - Add end-to-end snapshot tests with new type aliases in basic_types
… Introduces MatchArmSpans, expr_spans/pattern_spans/match_arm_spans maps, and captures spans during CST→HIR lowering.
…t to specific unreachable arms and match expressions instead of line 1.
…high line numbers
…ertions for Ty::Class and Ty::Enum. Update handling for Ty::List to include element types, and note that Ty::Map is not fully implemented yet.
Important
Based on #2828
Summary
This PR adds exhaustiveness checking and unreachable arm detection for match expressions in BAML's type system. The implementation uses a value-based model (
ValueSet) inspired by the treatment of pattern matching in TAPL.Key capabilities:
200 | 201)Key Design Decisions
1. Value-Based Model (ValueSet)
The core insight is that pattern matching operates on values, not types. A pattern like
Status.Activematches one specific value, whiles: Statusmatches all values of type Status.The
ValueSetenum captures this:This separation allows clean reasoning about what values each arm covers.
2. Guards Do NOT Contribute to Exhaustiveness
Per BEP-002, guarded patterns are treated as
Emptyvalue sets. A pattern likex: int if x > 0might not match negative numbers, so it can't guarantee coverage.3. Type Alias Expansion
Type aliases are expanded during exhaustiveness checking. For
type Result = Success | Failure, matching onr: Resultrequires covering bothSuccessandFailure.4. Finite vs. Infinite Types
OfTypesets, only exhaustive via catch-all5. Singleton Types for Literal Unions
Added singleton types (
Ty::Singleton(SingletonValue)) to support exhaustiveness checking of literal unions like200 | 201 | 204. This follows the type-theoretic notion of singleton types—types inhabited by exactly one value.Files Changed
baml_thir/src/exhaustiveness.rsValueSetabstraction,ExhaustivenessChecker, coverage algorithmsbaml_thir/src/lib.rsbaml_thir/src/types.rsTy::Singleton,SingletonValue, andis_uninhabited()methodbaml_hir/src/type_ref.rsTypeRef::StringLiteral,TypeRef::IntLiteral,TypeRef::BoolLiteralfor literal type supportbaml_hir/src/lib.rsAlgorithm Overview
The exhaustiveness checker maintains a list of covered
ValueSets as it processes arms:Expand scrutinee type into required value sets
For each arm, convert pattern to
ValueSet:After all arms, find uncovered value sets:
TypeError::NonExhaustiveMatchwith helpful error messageTest Coverage
The implementation includes unit tests for:
ValueSetdisplay formatting42is covered byintpattern)Known Limitations / Future Work
Error Span Improvements
Currently, unreachable arm errors point to the entire match expression rather than the specific unreachable arm. This requires tracking arm spans in HIR.
Uninhabited Types (Zero-Variant Enums)
Empty matches on uninhabited types should be allowed (there are no cases to handle). Currently only empty unions are detected; zero-variant enums require database access.
Cyclic Type Alias Detection
Recursive type aliases like
type A = A | Bcould cause infinite recursion during expansion. A cycle detection mechanism should be added.Example Usage