@samitouri / QOS-React / commits / e410815aeb

Infer more primitive types

Handles three more cases: * Template literals * deletion (property/computed) * type casts Only the latter has an observable impact, though i added tests for deletion just in case and found a bug. For type casts, they're reasonably common internally for fixmes, so this PR will help to ensure we don't drop type information just because of a cast.

Joe Savona committed Jun 4, 2023 at 20:27 UTC e410815aeb10bbef6406e09cf0783187fae34d2f
8 files changed +108 -5
compiler/forget/src/Inference/InferReferenceEffects.ts
+2 -1
@@ -837,7 +837,8 @@ function inferBlock(
837 state.reference(instrValue.object, Effect.Mutate);
838 state.reference(instrValue.property, Effect.Read);
839 state.initialize(instrValue, ValueKind.Immutable);
840 - state.reference(instr.lvalue, Effect.Mutate);
840 + state.define(instr.lvalue, instrValue);
841 + instr.lvalue.effect = Effect.Mutate;
842 continue;
843 }
844 case "ComputedLoad": {
compiler/forget/src/TypeInference/InferTypes.ts
+12 -4
@@ -108,6 +108,7 @@ function* generateInstructionTypes(
108 const left = lvalue.identifier.type;
109
110 switch (value.kind) {
111 + case "TemplateLiteral":
112 case "JSXText":
113 case "Primitive": {
114 yield equation(left, { kind: "Primitive" });
@@ -232,21 +233,28 @@ function* generateInstructionTypes(
233 break;
234 }
235
236 + case "TypeCastExpression": {
237 + yield equation(left, value.value.identifier.type);
238 + break;
239 + }
240 +
241 + case "PropertyDelete":
242 + case "ComputedDelete": {
243 + yield equation(left, { kind: "Primitive" });
244 + break;
245 + }
246 +
247 case "DeclareLocal":
248 case "DeclareContext":
249 case "NewExpression":
238 - case "TypeCastExpression":
250 case "JsxExpression":
251 case "JsxFragment":
252 case "RegExpLiteral":
253 case "PropertyStore":
243 - case "PropertyDelete":
254 case "ComputedStore":
255 case "ComputedLoad":
246 - case "ComputedDelete":
256 case "FunctionExpression":
257 case "TaggedTemplateExpression":
249 - case "TemplateLiteral":
258 case "Await":
259 case "NextIterableOf":
260 case "ExpressionStatement":
compiler/forget/src/__tests__/fixtures/compiler/infer-computed-delete.expect.md new
+25
@@ -0,0 +1,25 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @debug
6 +function Component(props) {
7 + const x = makeObject();
8 + const y = delete x[props.value];
9 + return y;
10 +}
11 +
12 +```
13 +
14 +## Code
15 +
16 +```javascript
17 +// @debug
18 +function Component(props) {
19 + const x = makeObject();
20 + const y = delete x[props.value];
21 + return y;
22 +}
23 +
24 +```
25 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/infer-computed-delete.js new
+6
@@ -0,0 +1,6 @@
1 +// @debug
2 +function Component(props) {
3 + const x = makeObject();
4 + const y = delete x[props.value];
5 + return y;
6 +}
compiler/forget/src/__tests__/fixtures/compiler/infer-property-delete.expect.md new
+23
@@ -0,0 +1,23 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + const x = makeObject();
7 + const y = delete x.value;
8 + return y;
9 +}
10 +
11 +```
12 +
13 +## Code
14 +
15 +```javascript
16 +function Component(props) {
17 + const x = makeObject();
18 + const y = delete x.value;
19 + return y;
20 +}
21 +
22 +```
23 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/infer-property-delete.js new
+5
@@ -0,0 +1,5 @@
1 +function Component(props) {
2 + const x = makeObject();
3 + const y = delete x.value;
4 + return y;
5 +}
compiler/forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.expect.md new
+26
@@ -0,0 +1,26 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +// @flow
6 +function Component(props) {
7 + // We can infer that `x` is a primitive bc it is aliased to `y`,
8 + // which is used in a binary expression
9 + const x = foo();
10 + const y = (x: any);
11 + y + 1;
12 + return x;
13 +}
14 +```
15 +
16 +## Code
17 +
18 +```javascript
19 +// @flow
20 +function Component(props) {
21 + const x = foo();
22 + return x;
23 +}
24 +
25 +```
26 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/infer-types-through-type-cast.flow.js new
+9
@@ -0,0 +1,9 @@
1 +// @flow
2 +function Component(props) {
3 + // We can infer that `x` is a primitive bc it is aliased to `y`,
4 + // which is used in a binary expression
5 + const x = foo();
6 + const y = (x: any);
7 + y + 1;
8 + return x;
9 +}
\ No newline at end of file