@samitouri / QOS-React / commits / de89ed32a2

Use implicit return (undefined)

Making ReturnTerminal.value non-nullable broke our optimization to elide final value-less return statements. We now check if a return value is explicitly `undefined` and elide the value in this case, which then also propagates to allow removing the final `return` statement of a function if the value is missing.

Joe Savona committed Apr 18, 2023 at 11:12 UTC de89ed32a2b649ad542a4f3387312aa3c171d3a7
51 files changed +82 -158
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+4
@@ -388,6 +388,10 @@ function codegenTerminal(
388 }
389 case "return": {
390 const value = codegenPlace(cx, terminal.value);
391 + if (value.type === "Identifier" && value.name === "undefined") {
392 + // Use implicit undefined
393 + return t.returnStatement();
394 + }
395 return t.returnStatement(value);
396 }
397 case "switch": {
compiler/forget/src/__tests__/fixtures/compiler/_bug.computed-call-evaluation-order.expect.md
-1
@@ -26,7 +26,6 @@ function Component() {
26 import * as React from "react"; // Should print A, B, arg, original
27 function changeF(o) {
28 o.f = () => console.log("new");
29 - return undefined;
29 }
30
31 function Component() {
compiler/forget/src/__tests__/fixtures/compiler/_bug.property-call-evaluation-order.expect.md
-1
@@ -26,7 +26,6 @@ import * as React from "react"; // Should print A, arg, original
26
27 function changeF(o) {
28 o.f = () => console.log("new");
29 - return undefined;
29 }
30
31 function Component() {
compiler/forget/src/__tests__/fixtures/compiler/alias-while.expect.md
+1 -3
@@ -50,9 +50,7 @@ function foo(cond) {
50 return a;
51 }
52
53 -function mutate(x, y) {
54 - return undefined;
55 -}
53 +function mutate(x, y) {}
54
55 ```
56
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/call.expect.md
+1 -3
@@ -19,9 +19,7 @@ function Component(props) {
19
20 ```javascript
21 import * as React from "react";
22 -function foo() {
23 - return undefined;
24 -}
22 +function foo() {}
23
24 function Component(props) {
25 const $ = React.unstable_useMemoCache(3);
compiler/forget/src/__tests__/fixtures/compiler/conditional-on-mutable.expect.md
+2 -6
@@ -105,12 +105,8 @@ function ComponentB(props) {
105 return t0;
106 }
107
108 -function Foo() {
109 - return undefined;
110 -}
111 -function mayMutate() {
112 - return undefined;
113 -}
108 +function Foo() {}
109 +function mayMutate() {}
110
111 ```
112
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/constructor.expect.md
+1 -3
@@ -19,9 +19,7 @@ function Component(props) {
19
20 ```javascript
21 import * as React from "react";
22 -function Foo() {
23 - return undefined;
24 -}
22 +function Foo() {}
23
24 function Component(props) {
25 const $ = React.unstable_useMemoCache(3);
compiler/forget/src/__tests__/fixtures/compiler/early-return.expect.md
+2 -2
@@ -18,9 +18,9 @@ function MyApp(props) {
18 ```javascript
19 function MyApp(props) {
20 if (props.cond) {
21 - return undefined;
21 + return;
22 } else {
23 - return undefined;
23 + return;
24 }
25 }
26
compiler/forget/src/__tests__/fixtures/compiler/for-return.expect.md
+1 -2
@@ -15,9 +15,8 @@ function Component(props) {
15 ```javascript
16 function Component(props) {
17 for (const i = 0; 0 < props.count; ) {
18 - return undefined;
18 + return;
19 }
20 - return undefined;
20 }
21
22 ```
compiler/forget/src/__tests__/fixtures/compiler/frozen-after-alias.expect.md
+2 -6
@@ -35,12 +35,8 @@ function Component() {
35 return b;
36 }
37
38 -function useFreeze() {
39 - return undefined;
40 -}
41 -function foo(x) {
42 - return undefined;
43 -}
38 +function useFreeze() {}
39 +function foo(x) {}
40
41 ```
42
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/hook-call.expect.md
+2 -6
@@ -23,12 +23,8 @@ function Component(props) {
23
24 ```javascript
25 import * as React from "react";
26 -function useFreeze() {
27 - return undefined;
28 -}
29 -function foo() {
30 - return undefined;
31 -}
26 +function useFreeze() {}
27 +function foo() {}
28
29 function Component(props) {
30 const $ = React.unstable_useMemoCache(3);
compiler/forget/src/__tests__/fixtures/compiler/hooks-freeze-arguments.expect.md
+2 -6
@@ -35,12 +35,8 @@ function Component() {
35 return a;
36 }
37
38 -function useFreeze(x) {
39 - return undefined;
40 -}
41 -function call(x) {
42 - return undefined;
43 -}
38 +function useFreeze(x) {}
39 +function call(x) {}
40
41 ```
42
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/hooks-freeze-possibly-mutable-arguments.expect.md
+2 -6
@@ -50,12 +50,8 @@ function Component(props) {
50 return a;
51 }
52
53 -function useFreeze(x) {
54 - return undefined;
55 -}
56 -function call(x) {
57 - return undefined;
58 -}
53 +function useFreeze(x) {}
54 +function call(x) {}
55
56 ```
57
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/independent-across-if.expect.md
+4 -12
@@ -37,18 +37,10 @@ function Component(props) {
37
38 ```javascript
39 import * as React from "react";
40 -function compute() {
41 - return undefined;
42 -}
43 -function mutate() {
44 - return undefined;
45 -}
46 -function foo() {
47 - return undefined;
48 -}
49 -function Foo() {
50 - return undefined;
51 -}
40 +function compute() {}
41 +function mutate() {}
42 +function foo() {}
43 +function Foo() {}
44
45 /**
46 * Should produce 3 scopes:
compiler/forget/src/__tests__/fixtures/compiler/independent.expect.md
+3 -9
@@ -74,15 +74,9 @@ function Component(props) {
74 return t2;
75 }
76
77 -function compute() {
78 - return undefined;
79 -}
80 -function foo() {
81 - return undefined;
82 -}
83 -function Foo() {
84 - return undefined;
85 -}
77 +function compute() {}
78 +function foo() {}
79 +function Foo() {}
80
81 ```
82
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/interdependent-across-if.expect.md
+3 -9
@@ -31,15 +31,9 @@ function Component(props) {
31
32 ```javascript
33 import * as React from "react";
34 -function compute() {
35 - return undefined;
36 -}
37 -function foo() {
38 - return undefined;
39 -}
40 -function Foo() {
41 - return undefined;
42 -}
34 +function compute() {}
35 +function foo() {}
36 +function Foo() {}
37
38 /**
39 * Should produce 1 scope:
compiler/forget/src/__tests__/fixtures/compiler/interdependent.expect.md
+3 -9
@@ -69,15 +69,9 @@ function Component(props) {
69 return t0;
70 }
71
72 -function compute() {
73 - return undefined;
74 -}
75 -function foo() {
76 - return undefined;
77 -}
78 -function Foo() {
79 - return undefined;
80 -}
72 +function compute() {}
73 +function foo() {}
74 +function Foo() {}
75
76 ```
77
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/issue852.expect.md
-1
@@ -17,7 +17,6 @@ function Component(c) {
17 function Component(c) {
18 const x = { c };
19 mutate(x);
20 - return undefined;
20 }
21
22 ```
compiler/forget/src/__tests__/fixtures/compiler/mutable-lifetime-loops.expect.md
+2 -7
@@ -42,12 +42,8 @@ function Component(props) {
42 ## Code
43
44 ```javascript
45 -function mutate(x, y) {
46 - return undefined;
47 -}
48 -function cond(x) {
49 - return undefined;
50 -}
45 +function mutate(x, y) {}
46 +function cond(x) {}
47
48 function Component(props) {
49 let a = {};
@@ -75,7 +71,6 @@ function Component(props) {
71 }
72
73 mutate(d, null);
78 - return undefined;
74 }
75
76 ```
compiler/forget/src/__tests__/fixtures/compiler/mutable-lifetime-with-aliasing.expect.md
+1 -4
@@ -38,9 +38,7 @@ function Component(props) {
38 ## Code
39
40 ```javascript
41 -function mutate(x, y) {
42 - return undefined;
43 -}
41 +function mutate(x, y) {}
42
43 function Component(props) {
44 const a = {};
@@ -63,7 +61,6 @@ function Component(props) {
61 }
62
63 mutate(x, null);
66 - return undefined;
64 }
65
66 ```
compiler/forget/src/__tests__/fixtures/compiler/mutable-liverange-loop.expect.md
+2 -7
@@ -37,12 +37,8 @@ function Component(props) {
37 ## Code
38
39 ```javascript
40 -function mutate() {
41 - return undefined;
42 -}
43 -function cond() {
44 - return undefined;
45 -}
40 +function mutate() {}
41 +function cond() {}
42
43 function Component(props) {
44 const a = {};
@@ -65,7 +61,6 @@ function Component(props) {
61 }
62
63 mutate(d, null);
68 - return undefined;
64 }
65
66 ```
compiler/forget/src/__tests__/fixtures/compiler/object-computed-access-assignment.expect.md
-1
@@ -15,7 +15,6 @@ function foo(a, b, c) {
15 function foo(a, b, c) {
16 a[b] = c[b];
17 a[3] = c[b * 4];
18 - return undefined;
18 }
19
20 ```
compiler/forget/src/__tests__/fixtures/compiler/object-properties.expect.md
-1
@@ -19,7 +19,6 @@ function foo(a, b, c) {
19 const y = b.c.d;
20 y.z = c.d.e;
21 foo(a.b.c);
22 - return undefined;
22 }
23
24 ```
compiler/forget/src/__tests__/fixtures/compiler/overlapping-scopes-interleaved-by-terminal.expect.md
-1
@@ -26,7 +26,6 @@ function foo(a, b, c) {
26
27 y.push(a);
28 x.push(b);
29 - return undefined;
29 }
30
31 ```
compiler/forget/src/__tests__/fixtures/compiler/overlapping-scopes-interleaved.expect.md
-1
@@ -19,7 +19,6 @@ function foo(a, b) {
19 const y = [];
20 x.push(a);
21 y.push(b);
22 - return undefined;
22 }
23
24 ```
compiler/forget/src/__tests__/fixtures/compiler/overlapping-scopes-shadowed.expect.md
-1
@@ -19,7 +19,6 @@ function foo(a, b) {
19 const y = [];
20 y.push(b);
21 x.push(a);
22 - return undefined;
22 }
23
24 ```
compiler/forget/src/__tests__/fixtures/compiler/overlapping-scopes-while.expect.md
-1
@@ -23,7 +23,6 @@ function foo(a, b, c) {
23 y.push(b);
24 x.push(a);
25 }
26 - return undefined;
26 }
27
28 ```
compiler/forget/src/__tests__/fixtures/compiler/return-undefined.expect.md new
+25
@@ -0,0 +1,25 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + if (props.cond) {
7 + return undefined;
8 + }
9 + return props.value;
10 +}
11 +
12 +```
13 +
14 +## Code
15 +
16 +```javascript
17 +function Component(props) {
18 + if (props.cond) {
19 + return;
20 + }
21 + return props.value;
22 +}
23 +
24 +```
25 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/return-undefined.js new
+6
@@ -0,0 +1,6 @@
1 +function Component(props) {
2 + if (props.cond) {
3 + return undefined;
4 + }
5 + return props.value;
6 +}
compiler/forget/src/__tests__/fixtures/compiler/reverse-postorder.expect.md
-1
@@ -54,7 +54,6 @@ function Component(props) {
54 } else {
55 }
56 }
57 - return undefined;
57 }
58
59 ```
compiler/forget/src/__tests__/fixtures/compiler/sequence-expression.expect.md
+1 -3
@@ -42,9 +42,7 @@ function sequence(props) {
42 return x;
43 }
44
45 -function foo() {
46 - return undefined;
47 -}
45 +function foo() {}
46
47 ```
48
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/simple-alias.expect.md
+1 -3
@@ -20,9 +20,7 @@ function foo() {
20
21 ```javascript
22 import * as React from "react";
23 -function mutate() {
24 - return undefined;
25 -}
23 +function mutate() {}
24 function foo() {
25 const $ = React.unstable_useMemoCache(1);
26 let c;
compiler/forget/src/__tests__/fixtures/compiler/ssa-call-jsx-2.expect.md
+1 -3
@@ -22,9 +22,7 @@ function Component(props) {
22
23 ```javascript
24 import * as React from "react"; // @Pass runMutableRangeAnalysis
25 -function foo() {
26 - return undefined;
27 -}
25 +function foo() {}
26
27 function Component(props) {
28 const $ = React.unstable_useMemoCache(3);
compiler/forget/src/__tests__/fixtures/compiler/ssa-call-jsx.expect.md
+1 -3
@@ -19,9 +19,7 @@ function Component(props) {
19
20 ```javascript
21 import * as React from "react";
22 -function foo() {
23 - return undefined;
24 -}
22 +function foo() {}
23
24 function Component(props) {
25 const $ = React.unstable_useMemoCache(3);
compiler/forget/src/__tests__/fixtures/compiler/ssa-complex-multiple-if.expect.md
+1 -3
@@ -20,9 +20,7 @@ function foo() {
20 ## Code
21
22 ```javascript
23 -function foo() {
24 - return undefined;
25 -}
23 +function foo() {}
24
25 ```
26
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-complex-single-if.expect.md
+1 -3
@@ -17,9 +17,7 @@ function foo() {
17 ## Code
18
19 ```javascript
20 -function foo() {
21 - return undefined;
22 -}
20 +function foo() {}
21
22 ```
23
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-if-else.expect.md
+1 -3
@@ -18,9 +18,7 @@ function foo() {
18 ## Code
19
20 ```javascript
21 -function foo() {
22 - return undefined;
23 -}
21 +function foo() {}
22
23 ```
24
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-nested-partial-phi.expect.md
-1
@@ -26,7 +26,6 @@ function foo(a, b, c) {
26 }
27 return x;
28 }
29 - return undefined;
29 }
30
31 ```
compiler/forget/src/__tests__/fixtures/compiler/ssa-newexpression.expect.md
+1 -3
@@ -17,9 +17,7 @@ function Component(props) {
17
18 ```javascript
19 import * as React from "react";
20 -function Foo() {
21 - return undefined;
22 -}
20 +function Foo() {}
21
22 function Component(props) {
23 const $ = React.unstable_useMemoCache(1);
compiler/forget/src/__tests__/fixtures/compiler/ssa-shadowing.expect.md
+1 -4
@@ -20,9 +20,7 @@ function Foo(cond) {
20 ## Code
21
22 ```javascript
23 -function log() {
24 - return undefined;
25 -}
23 +function log() {}
24
25 function Foo(cond) {
26 let str = "";
@@ -33,7 +31,6 @@ function Foo(cond) {
31 }
32
33 log(str);
36 - return undefined;
34 }
35
36 ```
compiler/forget/src/__tests__/fixtures/compiler/ssa-sibling-phis.expect.md
+1 -3
@@ -27,9 +27,7 @@ function foo(a, b, c, d) {
27 ## Code
28
29 ```javascript
30 -function foo(a, b, c, d) {
31 - return undefined;
32 -}
30 +function foo(a, b, c, d) {}
31
32 ```
33
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-simple-phi.expect.md
+1 -3
@@ -19,9 +19,7 @@ function foo() {
19 ## Code
20
21 ```javascript
22 -function foo() {
23 - return undefined;
24 -}
22 +function foo() {}
23
24 ```
25
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-simple.expect.md
+1 -3
@@ -12,9 +12,7 @@ function foo() {
12 ## Code
13
14 ```javascript
15 -function foo() {
16 - return undefined;
17 -}
15 +function foo() {}
16
17 ```
18
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-single-if.expect.md
+1 -3
@@ -16,9 +16,7 @@ function foo() {
16 ## Code
17
18 ```javascript
19 -function foo() {
20 - return undefined;
21 -}
19 +function foo() {}
20
21 ```
22
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/ssa-switch.expect.md
-1
@@ -38,7 +38,6 @@ function foo() {
38 default: {
39 }
40 }
41 - return undefined;
41 }
42
43 ```
compiler/forget/src/__tests__/fixtures/compiler/switch-with-fallthrough.expect.md
-1
@@ -55,7 +55,6 @@ function foo(x) {
55 default: {
56 }
57 }
58 - return undefined;
58 }
59
60 ```
compiler/forget/src/__tests__/fixtures/compiler/transitive-alias-fields.expect.md
-1
@@ -31,7 +31,6 @@ function component() {
31 q.y = p.y;
32
33 mutate(q);
34 - return undefined;
34 }
35
36 ```
compiler/forget/src/__tests__/fixtures/compiler/type-args-test-binary-operator.expect.md
-1
@@ -16,7 +16,6 @@ function component(a, b) {
16 function component(a, b) {
17 if (a > b) {
18 }
19 - return undefined;
19 }
20
21 ```
compiler/forget/src/__tests__/fixtures/compiler/type-binary-operator.expect.md
-1
@@ -20,7 +20,6 @@ function component() {
20 const b = someOther();
21 if (a > b) {
22 }
23 - return undefined;
23 }
24
25 ```
compiler/forget/src/__tests__/fixtures/compiler/useMemo-return-empty.expect.md
-1
@@ -18,7 +18,6 @@ function component(a) {
18 // @inlineUseMemo
19 function component(a) {
20 mutate(a);
21 - return undefined;
21 }
22
23 ```
compiler/forget/src/__tests__/fixtures/compiler/while-conditional-continue.expect.md
-1
@@ -28,7 +28,6 @@ function foo(a, b, c, d) {
28 }
29
30 d();
31 - return undefined;
31 }
32
33 ```