Join GitHub today
GitHub is home to over 40 million developers working together to host and review code, manage projects, and build software together.Sign up
provide counter example for total active patterns that are not exhaustively matched #823
let (|PA|PB|) x = match x with Some _ -> PA | _ -> PB let f = function | PA -> ()
it currently produces
I'd like the compiler to provide counter example of
Pros and Cons
Estimated cost: M
Please tick this by placing a cross in the box:
Please tick all that apply:
Would be a great addition to the heuristics, but it may be tricky if the active pattern matches are mixed with other active patterns, normal patterns in the same match statement.
Perhaps if we'd only implement the trivial case (one active pattern used in the match clauses, provided it's 'total') it'd be not too hard to do.
Following on from @abelbraaksma, I would have thought that
let (|PA|PB|) = function Some() -> PA | None -> PB let f(x:unit option) = match x with | PA -> () // | None -> () : if this is added, then "Incomplete pattern matches on this expression." // PB -> () : if this is added, the compiler is happy.
The compiler does seem to have special logic checking completeness for complete active pattern cases. This seems brittle for settings where active and other patterns are included in a match.
An implementation of this suggestion might need to expand the match, substituting the patterns (expanding
It should work as long as there is no non-terminating recursion:
/// should stall on runtime not compile time let rec (|PA|PB|) = function QA -> PA | QB -> PB and (|QA|QB|) = function PA -> QA | PB -> QB
Thanks for the comments, active patterns can be mixed and total active patterns aren't an exception; I totally overlooked that while making the suggestion,
Would it make sense to update the suggestion so that it applies for match expression when existing clauses are solely members of the active pattern definition, aka unmixed?
let (|PA|PB|) x = match x with Some _ -> PA | _ -> PB let f = function | PA -> () | None -> ()
would remain unchanged (warning without counter example, despite being a false positive)
If the exhaustiveness check could be handled as @charlesroddie explains it would be even better, but the restricted case intended for this suggestion maybe has better chance to be implemented.
@smoothdeveloper I agree. I think catching the general case is a good thing to have. Typically, one would use complete (or closed) active patterns to use them as a whole, so that the compiler only needs to call the active pattern function once. It seems to me that the available cases (internally, these are