[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
}