Add pattern match exhaustiveness checking

Implements the exhaustiveness algorithm to detect non-exhaustive pattern matches:
- Detects missing Bool patterns (true/false)
- Detects missing Option patterns (Some/None)
- Detects missing Result patterns (Ok/Err)
- Recognizes wildcards and variable patterns as catch-alls
- Warns about redundant patterns after catch-all patterns
- Integrates with the type checker to report errors

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-13 04:19:56 -05:00
parent d37f0fb096
commit db516f5cff
3 changed files with 544 additions and 0 deletions

View File

@@ -8,6 +8,7 @@ use crate::ast::{
TypeDecl, TypeExpr, UnaryOp, VariantFields,
};
use crate::diagnostics::{Diagnostic, Severity};
use crate::exhaustiveness::{check_exhaustiveness, missing_patterns_hint};
use crate::modules::ModuleLoader;
use crate::types::{
self, unify, EffectDef, EffectOpDef, EffectSet, HandlerDef, PropertySet, Type, TypeEnv,
@@ -988,6 +989,30 @@ impl TypeChecker {
}
}
// Check exhaustiveness
let exhaustiveness = check_exhaustiveness(&scrutinee_type, arms, &self.env);
if !exhaustiveness.is_exhaustive {
let hint = missing_patterns_hint(&exhaustiveness.missing_patterns);
self.errors.push(TypeError {
message: format!(
"Non-exhaustive pattern match. {}",
hint
),
span,
});
}
// Warn about redundant arms
for idx in exhaustiveness.redundant_arms {
self.errors.push(TypeError {
message: format!(
"Redundant pattern: this arm will never be matched because previous patterns cover all cases"
),
span: arms[idx].span,
});
}
result_type.unwrap_or(Type::Error)
}