mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[hir][typer] infer polymorphic types from PropertyLoad and PropertyCall
---
Expand Hindley Milner type inference to infer dependent types.
Say `t` is a typevar and `t'` is some type (a built-in type, phi node, or
another typevar).
Our type equations are as follows (please edit/correct notation 😅)
- type substitution: `t = t'`,
- ~~dependent~~ polymorphic property load: `t = t'.prop`
- polymorphic function call `t = fnCall{returnType}`
- ~~dependent property call: `t = t'.prop` (only if t'.prop is a function
type)~~
- ~~dependent return type: `t = t'.[[returntype]]`~~
This commit is contained in:
@@ -7,7 +7,7 @@ import {
|
||||
FunctionType,
|
||||
IdentifierId,
|
||||
makeIdentifierId,
|
||||
Type,
|
||||
ObjectType,
|
||||
ValueKind,
|
||||
} from "./HIR";
|
||||
import { BUILTIN_HOOKS, Hook } from "./Hooks";
|
||||
@@ -75,19 +75,23 @@ export class Environment {
|
||||
};
|
||||
}
|
||||
|
||||
getPropertyType(receiver: Type, property: string): BuiltInType | null {
|
||||
if (receiver.kind === "Object" || receiver.kind === "Function") {
|
||||
const { shapeId } = receiver;
|
||||
if (shapeId !== null) {
|
||||
const shape = BUILTIN_SHAPES.get(shapeId);
|
||||
invariant(
|
||||
shape !== undefined,
|
||||
`[HIR] Forget internal error: cannot resolve shape ${shapeId}`
|
||||
);
|
||||
return shape.properties.get(property) ?? null;
|
||||
}
|
||||
getPropertyType(
|
||||
receiver: ObjectType | FunctionType,
|
||||
property: string
|
||||
): BuiltInType | null {
|
||||
const { shapeId } = receiver;
|
||||
if (shapeId !== null) {
|
||||
// If an object or function has a shapeId, it must have been assigned
|
||||
// by Forget (and be present in a builtin or user-defined registry)
|
||||
const shape = BUILTIN_SHAPES.get(shapeId);
|
||||
invariant(
|
||||
shape !== undefined,
|
||||
`[HIR] Forget internal error: cannot resolve shape ${shapeId}`
|
||||
);
|
||||
return shape.properties.get(property) ?? null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getFunctionSignature(type: FunctionType): FunctionSignature | null {
|
||||
|
||||
@@ -231,13 +231,17 @@ class Unifier {
|
||||
unify(tA: Type, tB: Type | PolyType): void {
|
||||
if (tB.kind === "Property") {
|
||||
const objectType = this.get(tB.object);
|
||||
const propertyType = this.env.getPropertyType(
|
||||
objectType,
|
||||
tB.propertyName
|
||||
);
|
||||
if (propertyType !== null) {
|
||||
this.unify(tA, propertyType);
|
||||
if (objectType.kind === "Object" || objectType.kind === "Function") {
|
||||
const propertyType = this.env.getPropertyType(
|
||||
objectType,
|
||||
tB.propertyName
|
||||
);
|
||||
if (propertyType !== null) {
|
||||
this.unify(tA, propertyType);
|
||||
}
|
||||
}
|
||||
// We do not error if tB is not a known object or function (even if it
|
||||
// is a primitive), since JS implicit conversion to objects
|
||||
return;
|
||||
} else if (tB.kind === "FunctionCall") {
|
||||
this.unifyFunctionCall(tA, tB);
|
||||
|
||||
Reference in New Issue
Block a user