[compiler] Support logical assignment operators in BuildHIR#36733
Open
poteto wants to merge 2 commits into
Open
[compiler] Support logical assignment operators in BuildHIR#36733poteto wants to merge 2 commits into
poteto wants to merge 2 commits into
Conversation
Logical assignment operators (??=, &&=, ||=) currently bail out of compilation as BuildHIR todos in both the TypeScript compiler and the Rust port, so components using them are skipped entirely. Adds an error.todo fixture documenting the three todo errors emitted today. Repro for react#33315.
The logical assignment operators (??=, &&=, ||=) bailed out as BuildHIR todos in both the TypeScript compiler and the Rust port. Lower `a ??= b` as `a ?? (a = b)` (likewise for &&= and ||=), reusing the logical-expression value-block lowering so that the right-hand side and the store only evaluate when the assignment is taken. The target reference is lowered exactly once, before the logical terminal; because codegen re-emits unpromoted temporaries at each use site and the object and computed key of member targets are referenced by both the load and the conditional store, those temporaries are copied to promoted const temporaries unless they are plain identifier references. Desugaring approach adopted from react#36394 by Raashish Aggarwal, with the block construction aligned to LogicalExpression lowering, single evaluation of effectful member targets fixed, and the same lowering ported to the Rust compiler. Closes react#33315 Co-authored-by: Raashish Aggarwal <[email protected]>
45d34a8 to
5b8ee65
Compare
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.
??=,&&=, and||=were lowering todos in both compilers ("Handle ??= operators in AssignmentExpression"). Code using any logical assignment failed to compile.Both compilers now lower
a <op>= basa <op> (a = b)using the exact value-block structure of the existing LogicalExpression lowering: the RHS and the store live only in the alternate block, so they evaluate only when the assignment is taken, and the emitted JS is the canonical desugar.Member targets get single-evaluation semantics: the object and computed key are lowered once and, when they are not plain identifier references, copied into promoted const temporaries before the logical terminal. This is load-bearing: codegen re-emits unpromoted temporaries at each use site, so without the copy
obj[key()] ||= rhs()would emitobj[key()] || (obj[key()] = rhs())and callkey()twice. The fixture proves single evaluation at runtime (calls: {key: 1}) along with the short-circuit semantics for all three operators.Builds on #36394 by @raashish1601 (dispatch, desugar shape, target split), with the double-evaluation fix above and block construction restructured to match LogicalExpression lowering exactly so the TS and Rust pipelines stay in lockstep.
Related pre-existing issue, not addressed here: plain compound assignment has the same duplication bug on main today (
obj[key()] += 1evaluates the key twice). Same root cause class; will file separately.Verification: TS snap 1806/1806, Rust snap 1806/1806, cargo workspace green, scoped TS-vs-Rust HIR parity harness green.
Closes #33315