matching: minor simplification in do_for_multiple_match#13082
Merged
Conversation
(This is a small refactoring commit that should be obviously correct.) `do_for_multiple_match` is used to optimize code of the form `match e1, e2 with ...`, to avoid allocating a tuple `(e1, e2)` when possible (when the pattern does not require binding the scrutinee). (If the clause is `| (x, y) as p -> ...` for example, a binding `let p = (e1, e2) in ...` will still be emitted.) At first sight, its implementation is wrong. It precompiles a set of pattern-matching clauses whose scrutinee is a tuple of arbitrary expressions, and then it binds each of those expressions to a fresh variable and transforms the result of the precompilation to use these per-element variables instead of the tuple, to save an allocation. This is wrong because the arbitrary expressions may thus occur twice in the generated code, once in a `let p = (e1, e2)` binding generated by the precompilation, and another to bind the per-element variables. In fact this is okay because there is only one caller for `do_for_multiple_match`, and it always passes a tuple of expressions that are in fact variable, by performing an "outer binding" step that binds all the tuple elements to and calls `do_for_multiple_match` on a tuple of variables. So in fact there is no bug, and the fresh per-element variables in `do_for_multiple_match` are never useful. This redundant binding of variables was introduced in 2009 in f8107f9, to fix the bug described above (duplication of effectful expressions in the generated code), see ocaml#4828. The present commit simplifies and clarifies the code by changing `do_for_multiple_match` to take a list of variables instead of a list of expressions, and removing the redundant creation of per-element variables.
trefis
approved these changes
Apr 8, 2024
Member
Author
|
Thanks both for the prompt reviews, merging. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 is a small refactoring commit that should be obviously correct.)
do_for_multiple_matchis used to optimize code of the formmatch e1, e2 with ..., to avoid allocating a tuple(e1, e2)when possible (when the pattern does not require binding the scrutinee). (If the clause is| (x, y) as p -> ...for example, a bindinglet p = (e1, e2) in ...will still be emitted.)At first sight, its implementation is wrong. It precompiles a set of pattern-matching clauses whose scrutinee is a tuple of arbitrary expressions, and then it binds each of those expressions to a fresh variable and transforms the result of the precompilation to use these per-element variables instead of the tuple, to save an allocation. This is wrong because the arbitrary expressions may thus occur twice in the generated code, once in a
let p = (e1, e2)binding generated by the precompilation, and another to bind the per-element variables.In fact this is okay because there is only one caller for
do_for_multiple_match, and it always passes a tuple of expressions that are in fact variables, by performing an "outer binding" step that binds all the tuple elements to and callsdo_for_multiple_matchon a list of expressions-that-are-variables. So in fact there is no bug, and the fresh per-element variables indo_for_multiple_matchare never useful.This redundant binding of variables was introduced in 2009 in f8107f9, to fix the bug described above (duplication of effectful expressions in the generated code), see #4828.
The present commit simplifies and clarifies the code by changing
do_for_multiple_matchto take a list of variables instead of a list of expressions, and removing the redundant creation of per-element variables.(cc @ncik-roberts, @trefis, @Octachron, @lthls)