@samitouri / QOS-React-2 / commits / 0999b6b815

[hir] Treat captured refs in throw or return terminals as mutations

In a lambda, a return/throw terminal could return a captured context ref needs to be treated as a mutation to correctly alias the returned context ref and the lvalue.

Sathya Gunasekaran committed Mar 29, 2023 at 17:15 UTC 0999b6b81512ce8a190b04d8d46bfef61c542141
3 files changed +22 -21
compiler/forget/src/Inference/InferReferenceEffects.ts
+13 -4
@@ -893,11 +893,20 @@ function inferBlock(
893 instr.lvalue.effect = lvalueEffect;
894 }
895
896 - const effect =
897 - block.terminal.kind === "return" || block.terminal.kind === "throw"
898 - ? Effect.Freeze
899 - : Effect.Read;
896 for (const operand of eachTerminalOperand(block.terminal)) {
897 + let effect;
898 + if (block.terminal.kind === "return" || block.terminal.kind === "throw") {
899 + if (
900 + state.isDefined(operand) &&
901 + state.kind(operand) === ValueKind.Context
902 + ) {
903 + effect = Effect.Mutate;
904 + } else {
905 + effect = Effect.Freeze;
906 + }
907 + } else {
908 + effect = Effect.Read;
909 + }
910 state.reference(operand, effect);
911 }
912 }
compiler/forget/src/__tests__/fixtures/compiler/lambda-capture-returned-alias.expect.md renamed
+9 -17
@@ -33,7 +33,7 @@ function CaptureNotMutate(props) {
33 // - all other context refs are left as Unknown. InferReferenceEffects currently demotes
34 // them to reads
35 function CaptureNotMutate(props) {
36 - const $ = React.unstable_useMemoCache(7);
36 + const $ = React.unstable_useMemoCache(5);
37 const c_0 = $[0] !== props.x;
38 let t0;
39 if (c_0) {
@@ -45,30 +45,22 @@ function CaptureNotMutate(props) {
45 }
46 const idx = t0;
47 const c_2 = $[2] !== props.el;
48 - let t1;
49 - if (c_2) {
50 - t1 = bar(props.el);
51 - $[2] = props.el;
52 - $[3] = t1;
53 - } else {
54 - t1 = $[3];
55 - }
56 - const element = t1;
57 - const c_4 = $[4] !== element;
58 - const c_5 = $[5] !== idx;
48 + const c_3 = $[3] !== idx;
49 let aliasedElement;
60 - if (c_4 || c_5) {
50 + if (c_2 || c_3) {
51 + const element = bar(props.el);
52 +
53 const fn = function () {
54 const arr = { element };
55 return arr[idx];
56 };
57 aliasedElement = fn();
58 mutate(aliasedElement);
67 - $[4] = element;
68 - $[5] = idx;
69 - $[6] = aliasedElement;
59 + $[2] = props.el;
60 + $[3] = idx;
61 + $[4] = aliasedElement;
62 } else {
71 - aliasedElement = $[6];
63 + aliasedElement = $[4];
64 }
65 return aliasedElement;
66 }
compiler/forget/src/__tests__/fixtures/compiler/lambda-capture-returned-alias.js renamed