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