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
More robust matches #1518
More robust matches #1518
Conversation
(Beware: once again github decides to sort commit by their creation time, not topologically) |
OK actually, parmatch is still broken after this patch
I'm... looking. |
d04fd9c
to
2d484c1
Compare
Alright, new approach: The ideaFirst, notice that I believe we can change The implementationThere are a few things that might seem surprising when looking at the "coherence" check being run by
type t = A | B | C
type _ repr = R1 : unit repr | R2 : t repr
let f (type a) (r1 : a repr) (r2 : a repr) (a : a) =
match r1, r2, a with
| R1, _, () -> ()
| _, R2, C -> ()
|
|
Should we try to meet in person (with @maranget) to explain/discuss/review the patch? |
02bff72
to
73204ec
Compare
73204ec
to
6a0cc6a
Compare
Some of the changes of these GPR are being proposed separately in #1538 , while the rest needs to be slightly reworked and will be proposed in a later PR. Closing. |
As noted in #1493 various places in parmatch and matching work under the assumption that patterns in the same column will be of the same type, which is just wrong.
Parmatch
Two places made such an assumption:
Compat.compat(s)
: it expected the patterns it is called on to be of the same kind. There is no need to have such an assumption, considering patterns of different "kinds" as incompatible is corrrect.build_other
:the function in charge of building a value not being matched by a matching when we know the matching to be non-exhaustive.This function works by listing all the "constructors" of a type present on the first column, and then returning a constructor of type which is not in that list.Here we need to account for the fact that all the patterns in the first column are not necessarily of the same type.full_match
: cf. More robust matches #1518 (comment)I checked the other
assert false
andfatal_error
present in the file, I believe they are present for other reasons than "oh, these two things can only be of the same type".Matching
We sometimes make that assumption when specializing the list of reachable trap-handlers. This was the case when specializing by a record, a tuple, or a lazy pattern.
We now do some kind checking there and when things are of the same kind (two tuples, two records or two lazys) we do, here too, resort to arity checking.
Just as constructor of extensible types, these two cases, as well as array patterns, would benefit from some kind of compatibility checking based on typing information.
This is however not crucial and non-trivial to do well, so let's consider it at a later date.
Does this PR cover all the cases?
I believe so, but of course can't be sure.
My process was to look at all the
assert false
in parmatch justified by the said assumption, writing a test breaking the assumption, fixing the code, making sure the test passed.While doing this, I would sometimes get a assertion failure/fatal error in matching.
This happened for records in the expected way (that is: we already knew records weren't handled well), as well as for tuples.
I then looking at all the
matcher_*
functions, and apart frommatcher_lazy
, they all seemed sensible to me; that is: they all raisedNoMatch
instead of failing, which seems right.