parmatch: always check partiality#1227
Conversation
|
One reason to disable the partiality check when the warning is off is that the check itself can be costly. |
|
Yes indeed. We could make it quicker by explicitly looking for a wildcard row at the start of |
|
(N.B. by "revisit this choice" I mean "have both safe guards") |
Is anyone aware of people actually disabling the partiality check (resp. doing so for compilation-time performance)? |
gasche
left a comment
There was a problem hiding this comment.
As I mentioned otherwise, I think that the two commits should be squashed because the first one in isolation does not appear to be correct: it may generate an All_clauses_guarded warning even when Fragile_match is not set, while the latter would previously prevent the former.
The proposed code seems more correct than the previous one, because previously we would test whether Partial_match is active and assume that this implies that Fragile_match is active, if I understand correctly.
Why was this the case? I believe that this is related to the "8, used to be 25" comment, and I remember that we discussed this (myself included) recently, but I don't remember what was the discussion and what exactly this means.
Could someone point out to the old discussion and confirm that, based on the current relations between the two warnings, the PR indeed exactly preserves the compiler's behavior?
|
I reviewed the code and I believe that the proposed code is correct (I'm not sure the previous behavior was fully equivalent, see comment above). On the other hand, I find Jacques' performance concern interesting and I would like to have some information on that before considering a merge. @trefis, could you measure the time of "make world" with the patch applied, versus the time of "make world" without the patch and with all exhaustivity warnings disabled? Is there a noticeable difference? (Note: this uses only bytecode compilation, as native code production would risk drowning out this cost, and this is assuming that the OCaml compiler code is somewhat representative of average code full of pattern matchings -- but it doesn't tell us anything about degenerate cases.) I would be interested in having the heuristic you describe implemented (not doing any check when there is an all-omega row), but I don't really understand your comment on |
|
Thanks for having a look :) For the "benchmark" you propose I doubt we'd notice much difference on the compiler but I don't mind trying it. Question though: to test compiling the compiler with a compiler containing these patches, do I want to Btw, #1195 is not the first bit of code using the partiality information stored in the typedtree: if I am not mistaken I wouldn't change |
|
Rather than the whole compiler, it would probably be sufficient to test compiling the |
|
I compiled the stdlib a few times with trunk and with the this branch. I then compiled camlinternalFormat.ml a bunch of times with both compilers, as it contains some GADT matching. Of course, there's AFAIK nothing in these test cases which would exhibit the degenerate behavior of parmatch... stdlibWarnings 4, 8, 25 disabled (using this patch). trunk
GPR1227
camlinternalFormat$ time for i in {1..20}; do ../boot/ocamlrun ../ocamlc -strict-sequence -absname -w +a-4-8-9-25-41-42-44-45-48 -g -warn-error A -bin-annot -nostdlib -safe-string -strict-formats -w Ae-4-8-25 -c camlinternalFormat.ml; done
|
|
Btw, I think the second commit actually has no impact at all. |
|
FWIW, I asked internally at facebook and no one admitted to disabling the partiality check. The potential of missed optimization seemed to be considered a much more important "gotcha". So support for this PR on those grounds. |
|
@maranget should look at this PR and confirm, but as far as I remember the worst case is exponential in the size of the matching. A workaround that is quadratic is no big deal. |
|
@garrigue and @xavierleroy are right: adding a catch all clause at the end of a matching will My real objection against @garrigue suggestion is: if the matching was exhaustive then we'll have a unsused match clause warning. But again, this is a potential problem not a reported one. So I'll (squash and) merge the patch(es). |
Co-authored-by: cuihtlauac <cuihtlauac@users.noreply.github.com>
The partiality of a matching was only being computed when warning 8 is on.
This would be fine if all this function did was warn about the partiality of the match, but it actually returns a
Total | Partialresult which is then stored in the typedtree.Currently when the warning is off
Partialis always returned, while this seems safe it is inaccurate and might prevent "optimizations" relying on it from triggering, as is the case in #1195 for example.This PR changes the implementation to always compute the correct information, and do the warning part only when the warning is on.