The Pattern-Matching Bug: introduce a temporality heuristic to de-pessimize certain programs #13154
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
(This PR sits on top of #13152 and #13153; for now it is best reviewed by looking only at the latest commit.)
#13152 pessimizes Total matches in transitively mutable position. It gives two examples of code that now generates worse code:
In the case A, the generated code first checks something about the argument root.0, then it checks a guard, then it goes back to the argument root.0. (We say that there are two "splits", resulting in three submatrices, that are checked in sequence.) When it goes back to root.0, its value could have changed in the meantime, so assuming that root.0.0 could only be
false
is wrong, and we really needed to make the code worse.In the case B, the generated code reads the mutable field root.0, then immediately checks all possible cases on this constructor. In this case there cannot have been any mutation "in the meantime", this is the first time ever that we are checking this value. So generating a
Match_failure
case here was not necessary, and we are generating worse code than we could.In general it is hard to know for sure "this is the first time we do something on this value". Tracking this precisely might be done with more context information, but it would be a tricky change with quickly diminishing returns. There is however a case where it is very easy to see that we are in this situation: where we have not generated any "split", any logic of the form "check this about the first value, and if that fails check that".
The present PR introduces a new piece of static context information used by the pattern-matching compiler to track this criterion. In code:
When deciding whether a switch on a given position should be pessimized, we now use a refined criterion: we are in a transitively mutable position and the current temporality is
Following
, we have already accessed this position before.In particular, the example
g
above now produces good code again, as well as any reasonable usage of GADTs in mutable positions that I can think of.It is, of course, possible to build examples where the heuristic is too coarse-grained and which will generate worse code than they could. For example: