mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Use type assertions to drive inference
This PR uses the information from type cast expressions (`as` or `(variable: type)`) to inform type inference. BuildHIR converts the type annotation to our internal type format where possible, falling back to the generic `makeType()`. This is then used in InferTypes to help set the value's type.
This commit is contained in:
@@ -41,10 +41,12 @@ import {
|
||||
SourceLocation,
|
||||
SpreadPattern,
|
||||
ThrowTerminal,
|
||||
Type,
|
||||
makeInstructionId,
|
||||
makeType,
|
||||
} from "./HIR";
|
||||
import HIRBuilder, { Bindings } from "./HIRBuilder";
|
||||
import { BuiltInArrayId } from "./ObjectShape";
|
||||
|
||||
/*
|
||||
* *******************************************************************************************
|
||||
@@ -2148,21 +2150,23 @@ function lowerExpression(
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
let expr = exprPath as NodePath<t.TypeCastExpression>;
|
||||
const typeAnnotation = expr.get("typeAnnotation").get("typeAnnotation");
|
||||
return {
|
||||
kind: "TypeCastExpression",
|
||||
value: lowerExpressionToTemporary(builder, expr.get("expression")),
|
||||
typeAnnotation: expr.get("typeAnnotation").get("typeAnnotation").node,
|
||||
type: makeType(),
|
||||
typeAnnotation: typeAnnotation.node,
|
||||
type: lowerType(builder, typeAnnotation),
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
case "TSAsExpression": {
|
||||
let expr = exprPath as NodePath<t.TSAsExpression>;
|
||||
const typeAnnotation = expr.get("typeAnnotation");
|
||||
return {
|
||||
kind: "TypeCastExpression",
|
||||
value: lowerExpressionToTemporary(builder, expr.get("expression")),
|
||||
typeAnnotation: expr.get("typeAnnotation").node,
|
||||
type: makeType(),
|
||||
typeAnnotation: typeAnnotation.node,
|
||||
type: lowerType(builder, typeAnnotation),
|
||||
loc: exprLoc,
|
||||
};
|
||||
}
|
||||
@@ -3791,3 +3795,52 @@ function gatherCapturedDeps(
|
||||
function notNull<T>(value: T | null): value is T {
|
||||
return value !== null;
|
||||
}
|
||||
|
||||
function lowerType(
|
||||
_builder: HIRBuilder,
|
||||
path: NodePath<t.FlowType | t.TSType>
|
||||
): Type {
|
||||
const node = path.node;
|
||||
switch (node.type) {
|
||||
case "GenericTypeAnnotation": {
|
||||
const typeAnnotation = path as NodePath<t.GenericTypeAnnotation>;
|
||||
const id = typeAnnotation.get("id");
|
||||
if (id.node.type === "Identifier" && id.node.name === "Array") {
|
||||
return { kind: "Object", shapeId: BuiltInArrayId };
|
||||
}
|
||||
return makeType();
|
||||
}
|
||||
case "TSTypeReference": {
|
||||
const typeReference = path as NodePath<t.TSTypeReference>;
|
||||
const typeName = typeReference.get("typeName").node;
|
||||
if (typeName.type === "Identifier" && typeName.name === "Array") {
|
||||
return { kind: "Object", shapeId: BuiltInArrayId };
|
||||
}
|
||||
return makeType();
|
||||
}
|
||||
case "ArrayTypeAnnotation":
|
||||
case "TSArrayType": {
|
||||
return { kind: "Object", shapeId: BuiltInArrayId };
|
||||
}
|
||||
case "BooleanLiteralTypeAnnotation":
|
||||
case "BooleanTypeAnnotation":
|
||||
case "NullLiteralTypeAnnotation":
|
||||
case "NumberLiteralTypeAnnotation":
|
||||
case "NumberTypeAnnotation":
|
||||
case "StringLiteralTypeAnnotation":
|
||||
case "StringTypeAnnotation":
|
||||
case "TSBooleanKeyword":
|
||||
case "TSNullKeyword":
|
||||
case "TSNumberKeyword":
|
||||
case "TSStringKeyword":
|
||||
case "TSSymbolKeyword":
|
||||
case "TSUndefinedKeyword":
|
||||
case "TSVoidKeyword":
|
||||
case "VoidTypeAnnotation": {
|
||||
return { kind: "Primitive" };
|
||||
}
|
||||
default: {
|
||||
return makeType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,7 +373,9 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
|
||||
break;
|
||||
}
|
||||
case "TypeCastExpression": {
|
||||
value = `TypeCast ${printPlace(instrValue.value)}`;
|
||||
value = `TypeCast ${printPlace(instrValue.value)}: ${printType(
|
||||
instrValue.type
|
||||
)}`;
|
||||
break;
|
||||
}
|
||||
case "JsxExpression": {
|
||||
|
||||
@@ -262,7 +262,8 @@ function* generateInstructionTypes(
|
||||
}
|
||||
|
||||
case "TypeCastExpression": {
|
||||
yield equation(left, value.value.identifier.type);
|
||||
yield equation(value.type, value.value.identifier.type);
|
||||
yield equation(left, value.type);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+31
-10
@@ -2,14 +2,16 @@
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
import { identity } from "shared-runtime";
|
||||
|
||||
function Component(props: { id: number }) {
|
||||
const x = [props.id] as number[];
|
||||
const y = identity(x[0]);
|
||||
const x = makeArray(props.id) as number[];
|
||||
const y = x.at(0);
|
||||
return y;
|
||||
}
|
||||
|
||||
function makeArray<T>(x: T): Array<T> {
|
||||
return [x];
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ id: 42 }],
|
||||
@@ -21,23 +23,42 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
import { identity } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const $ = useMemoCache(4);
|
||||
let t0;
|
||||
if ($[0] !== props.id) {
|
||||
const x = [props.id] as number[];
|
||||
t0 = identity(x[0]);
|
||||
t0 = makeArray(props.id);
|
||||
$[0] = props.id;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const y = t0;
|
||||
const x = t0 as number[];
|
||||
let t1;
|
||||
if ($[2] !== x) {
|
||||
t1 = x.at(0);
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const y = t1;
|
||||
return y;
|
||||
}
|
||||
|
||||
function makeArray(x) {
|
||||
const $ = useMemoCache(2);
|
||||
let t0;
|
||||
if ($[0] !== x) {
|
||||
t0 = [x];
|
||||
$[0] = x;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ id: 42 }],
|
||||
|
||||
+6
-4
@@ -1,11 +1,13 @@
|
||||
import { identity } from "shared-runtime";
|
||||
|
||||
function Component(props: { id: number }) {
|
||||
const x = [props.id] as number[];
|
||||
const y = identity(x[0]);
|
||||
const x = makeArray(props.id) as number[];
|
||||
const y = x.at(0);
|
||||
return y;
|
||||
}
|
||||
|
||||
function makeArray<T>(x: T): Array<T> {
|
||||
return [x];
|
||||
}
|
||||
|
||||
export const FIXTURE_ENTRYPOINT = {
|
||||
fn: Component,
|
||||
params: [{ id: 42 }],
|
||||
|
||||
+16
-8
@@ -3,11 +3,11 @@
|
||||
|
||||
```javascript
|
||||
// @flow
|
||||
import { identity } from "shared-runtime";
|
||||
import { identity, makeArray } from "shared-runtime";
|
||||
|
||||
function Component(props: { id: number }) {
|
||||
const x = ([props.id]: Array<number>);
|
||||
const y = identity(x[0]);
|
||||
const x = (makeArray(props.id): Array<number>);
|
||||
const y = x.at(0);
|
||||
return y;
|
||||
}
|
||||
|
||||
@@ -22,20 +22,28 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
import { identity } from "shared-runtime";
|
||||
import { identity, makeArray } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
const $ = useMemoCache(4);
|
||||
let t0;
|
||||
if ($[0] !== props.id) {
|
||||
const x = ([props.id]: Array<number>);
|
||||
t0 = identity(x[0]);
|
||||
t0 = makeArray(props.id);
|
||||
$[0] = props.id;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const y = t0;
|
||||
const x = (t0: Array<number>);
|
||||
let t1;
|
||||
if ($[2] !== x) {
|
||||
t1 = x.at(0);
|
||||
$[2] = x;
|
||||
$[3] = t1;
|
||||
} else {
|
||||
t1 = $[3];
|
||||
}
|
||||
const y = t1;
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
// @flow
|
||||
import { identity } from "shared-runtime";
|
||||
import { identity, makeArray } from "shared-runtime";
|
||||
|
||||
function Component(props: { id: number }) {
|
||||
const x = ([props.id]: Array<number>);
|
||||
const y = identity(x[0]);
|
||||
const x = (makeArray(props.id): Array<number>);
|
||||
const y = x.at(0);
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
+1
-11
@@ -20,20 +20,10 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
import { identity } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
let t0;
|
||||
if ($[0] !== props.id) {
|
||||
t0 = identity(props.id);
|
||||
$[0] = props.id;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const x = t0;
|
||||
const x = identity(props.id);
|
||||
const y = x as number;
|
||||
return y;
|
||||
}
|
||||
|
||||
+1
-11
@@ -21,20 +21,10 @@ export const FIXTURE_ENTRYPOINT = {
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
import { identity } from "shared-runtime";
|
||||
|
||||
function Component(props) {
|
||||
const $ = useMemoCache(2);
|
||||
let t0;
|
||||
if ($[0] !== props.id) {
|
||||
t0 = identity(props.id);
|
||||
$[0] = props.id;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
const x = t0;
|
||||
const x = identity(props.id);
|
||||
const y = (x: number);
|
||||
return y;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,10 @@ export function makeObject_Primitives(): StringKeyedObject {
|
||||
return { a: 0, b: "value1", c: true };
|
||||
}
|
||||
|
||||
export function makeArray<T>(value: T): Array<T> {
|
||||
return [value];
|
||||
}
|
||||
|
||||
export function addOne(value: number): number {
|
||||
return value + 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user