[compiler] Count loop reassignments as the enclosing scope reassignin…
GitHub Commits - Example: React Grade 10

[compiler] Count loop reassignments as the enclosing scope reassignin…

[compiler] Count loop reassignments as the enclosing scope reassigning the variable (#36732) A counter initialized before a memo scope and incremented inside it (`a++` or `a = a + 1` in a `for` body) was emitted as a scope *dependency*, compared at its pre-loop value (constant every render) while the cache stored its post-loop value. The memo could never hit, so the scope recomputed on every render. Root cause: the phi-union rule in `InferReactiveScopeVariables.findDisjointMutableValues` only unioned a phi into the scope when the phi value was mutated after creation, which range-extension only does for object mutation. Primitive reassignments around a loop back-edge never extend ranges, so the counter's SSA versions stayed outside the scope and downstream dependency propagation classified the pre-loop read as a dep. The fix unions a phi with its operands and declaration when any operand is defined at or after the phi's block, i.e. the value is reassigned around a loop back-edge. This matches the shape the compiler already produced for non-primitive loop reassignment (`x = [...x, i]`). Implemented identically in the TypeScript compiler and the Rust port. Both `a++` and `a = a + 1` variants are pinned by fixtures; the first commit documents the previously-wrong codegen, the second fixes it (counter becomes a scope output, dep on `count` only). Corpus delta beyond the new fixtures is 4 fixtures, all strict improvements with byte-identical eval output: `for-in-statement-break`, `for-in-statement-continue`, `for-in-statement-type-inference` (loops previously re-ran every render, now memoized), and `sequence-expression` (two memo blocks collapse into one). Known limitation, unchanged from before: conditional reassignment in a loop (`for (...) { if (c) a++; }`) routes through a join phi that this rule cannot see; that shape behaves as it did before this change. Verification: TS snap 1806/1806, Rust snap 1806/1806, cargo workspace green, scoped TS-vs-Rust HIR parity harness green. Closes #34971

Commit 0ca9d20 authored [compiler] Count loop reassignments as the enclosing scope reassigning the variable (#36732) A counter initialized before a memo scope and incremented inside it (`a++` or `a = a + 1` in a `for` body) was emitted as a scope *dependency*, compared at its pre-loop value (constant every render) while the cache stored its post-loop value. The memo could never hit, so the scope recomputed on every render. Root cause: the phi-union rule in `InferReactiveScopeVariables.findDisjointMutableValues` only unioned a phi into the scope when the phi value was mutated after creation, which range-extension only does for object mutation. Primitive reassignments around a loop back-edge never extend ranges, so the counter's SSA versions stayed outside the scope and downstream dependency propagation classified the pre-loop read as a dep. The fix unions a phi with its operands and declaration when any operand is defined at or after the phi's block, i.e. the value is reassigned around a loop back-edge. This matches the shape the compiler already produced for non-primitive loop reassignment (`x = [...x, i]`). Implemented identically in the TypeScript compiler and the Rust port. Both `a++` and `a = a + 1` variants are pinned by fixtures; the first commit documents the previously-wrong codegen, the second fixes it (counter becomes a scope output, dep on `count` only). Corpus delta beyond the new fixtures is 4 fixtures, all strict improvements with byte-identical eval output: `for-in-statement-break`, `for-in-statement-continue`, `for-in-statement-type-inference` (loops previously re-ran every render, now memoized), and `sequence-expression` (two memo blocks collapse into one). Known limitation, unchanged from before: conditional reassignment in a loop (`for (...) { if (c) a++; }`) routes through a join phi that this rule cannot see; that shape behaves as it did before this change. Verification: TS snap 1806/1806, Rust snap 1806/1806, cargo workspace green, scoped TS-vs-Rust HIR parity harness green. Closes #349711 parent 77df6e1 commit 0ca9d20 10 files changed Lines changed: 238 additions & 45 deletions File tree - compiler - crates/react_compiler_inference/src - packages/babel-plugin-react-compiler/src - ReactiveScopes - __tests__/fixtures/compiler Lines changed: 20 additions & 1 deletion | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 284 | 284 | | | 285 | 285 | | | 286 | 286 | | | 287 | | - | | | 287 | + | | | 288 | + | | | 289 | + | | | 290 | + | | | 291 | + | | | 292 | + | | | 293 | + | | | 294 | + | | | 295 | + | | | 296 | + | | | 297 | + | | | 298 | + | | | 299 | + | | | 300 | + | | | 301 | + | | | 302 | + | | | 303 | + | | | 304 | + | | | 305 | + | | | 306 | + | | 288 | 307 | | | 289 | 308 | | | 290 | 309 | | | | Lines changed: 24 additions & 5 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 25 | 25 | | | 26 | 26 | | | 27 | 27 | | | 28 | | - | | | 28 | + | | 29 | 29 | | | 30 | 30 | | | 31 | 31 | | | | ||| 287 | 287 | | | 288 | 288 | | | 289 | 289 | | | 290 | | - | | | 290 | + | | | 291 | + | | | 292 | + | | 291 | 293 | | | 292 | 294 | | | 293 | | - | | 294 | | - | | 295 | | - | | | 295 | + | | | 296 | + | | | 297 | + | | | 298 | + | | | 299 | + | | | 300 | + | | | 301 | + | | | 302 | + | | | 303 | + | | | 304 | + | | | 305 | + | | | 306 | + | | | 307 | + | | | 308 | + | | | 309 | + | | | 310 | + | | | 311 | + | | | 312 | + | | | 313 | + | | | 314 | + | | 296 | 315 | | | 297 | 316 | | | 298 | 317 | | | | Lines changed: 10 additions & 12 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 29 | 29 | | | 30 | 30 | | | 31 | 31 | | | 32 | | - | | 33 | 32 | | | 34 | | - | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | | 40 | + | | 35 | 41 | | | 36 | | - | | | 42 | + | | 37 | 43 | | | 38 | | - | | 39 | | - | | 40 | | - | | 41 | | - | | 42 | | - | | 43 | | - | | 44 | | - | | 45 | | - | | 46 | | - | | | 44 | + | | 47 | 45 | | | 48 | 46 | | | 49 | 47 | | | | Lines changed: 10 additions & 12 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 38 | 38 | | | 39 | 39 | | | 40 | 40 | | | 41 | | - | | 42 | 41 | | | 43 | | - | | | 42 | + | | | 43 | + | | | 44 | + | | | 45 | + | | | 46 | + | | | 47 | + | | | 48 | + | | | 49 | + | | 44 | 50 | | | 45 | | - | | | 51 | + | | 46 | 52 | | | 47 | | - | | 48 | | - | | 49 | | - | | 50 | | - | | 51 | | - | | 52 | | - | | 53 | | - | | 54 | | - | | 55 | | - | | | 53 | + | | 56 | 54 | | | 57 | 55 | | | 58 | 56 | | | | Lines changed: 11 additions & 4 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 25 | 25 | | | 26 | 26 | | | 27 | 27 | | | 28 | | - | | | 28 | + | | 29 | 29 | | | 30 | 30 | | | 31 | 31 | | | | 32 | + | | 32 | 33 | | | 33 | | - | | 34 | | - | | 35 | | - | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | | 40 | + | | | 41 | + | | | 42 | + | | 36 | 43 | | | 37 | 44 | | | 38 | 45 | | | | Lines changed: 62 additions & 0 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | | | 18 | + | | | 19 | + | | | 20 | + | | | 21 | + | | | 22 | + | | | 23 | + | | | 24 | + | | | 25 | + | | | 26 | + | | | 27 | + | | | 28 | + | | | 29 | + | | | 30 | + | | | 31 | + | | | 32 | + | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | | 40 | + | | | 41 | + | | | 42 | + | | | 43 | + | | | 44 | + | | | 45 | + | | | 46 | + | | | 47 | + | | | 48 | + | | | 49 | + | | | 50 | + | | | 51 | + | | | 52 | + | | | 53 | + | | | 54 | + | | | 55 | + | | | 56 | + | | | 57 | + | | | 58 | + | | | 59 | + | | | 60 | + | | | 61 | + | | | 62 | + | Lines changed: 17 additions & 0 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | Lines changed: 62 additions & 0 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | | | 18 | + | | | 19 | + | | | 20 | + | | | 21 | + | | | 22 | + | | | 23 | + | | | 24 | + | | | 25 | + | | | 26 | + | | | 27 | + | | | 28 | + | | | 29 | + | | | 30 | + | | | 31 | + | | | 32 | + | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | | 40 | + | | | 41 | + | | | 42 | + | | | 43 | + | | | 44 | + | | | 45 | + | | | 46 | + | | | 47 | + | | | 48 | + | | | 49 | + | | | 50 | + | | | 51 | + | | | 52 | + | | | 53 | + | | | 54 | + | | | 55 | + | | | 56 | + | | | 57 | + | | | 58 | + | | | 59 | + | | | 60 | + | | | 61 | + | | | 62 | + | Lines changed: 17 additions & 0 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | Lines changed: 5 additions & 11 deletions | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 19 | 19 | | | 20 | 20 | | | 21 | 21 | | | 22 | | - | | 23 | | - | | | 22 | + | | | 23 | + | | 24 | 24 | | | 25 | | - | | 26 | | - | | 27 | | - | | 28 | | - | | 29 | | - | | 30 | | - | | 31 | | - | | | 25 | + | | 32 | 26 | | | 33 | 27 | | | 34 | 28 | | | 35 | | - | | | 29 | + | | 36 | 30 | | | 37 | | - | | | 31 | + | | 38 | 32 | | | 39 | 33 | | | 40 | 34 | | | | 0 commit comments

Comments

No comments yet. Start the discussion.