@samitouri / QOS-React-2 / commits / c130bcc9c2

[typer] Use opaque TypeId to number types

Sathya Gunasekaran committed Dec 20, 2022 at 14:55 UTC c130bcc9c2a6ad1922ca6da5ced2ad5c8a40cfb1
2 files changed +36 -20
compiler/forget/src/HIR/HIR.ts
+18 -3
@@ -460,17 +460,32 @@ export type ObjectType = { kind: "Object"; properties: Map<string, Type> };
460 export type PropType = { kind: "Prop"; objectType: Type; name: string };
461 export type TypeVar = {
462 kind: "Type";
463 - name: string;
463 + id: TypeId;
464 };
465 export type PolyType = {
466 kind: "Poly";
467 };
468
469 +/**
470 + * Simulated opaque type for TypeId to prevent using normal numbers as ids
471 + * accidentally.
472 + */
473 +const opaqueTypeId = Symbol();
474 +export type TypeId = number & { [opaqueTypeId]: "IdentifierId" };
475 +
476 +export function makeTypeId(id: number): TypeId {
477 + invariant(
478 + id >= 0 && Number.isInteger(id),
479 + "Expected instruction id to be a non-negative integer"
480 + );
481 + return id as TypeId;
482 +}
483 +
484 let typeCounter = 0;
485 export function makeType(): TypeVar {
486 return {
487 kind: "Type",
473 - name: `t${typeCounter++}`, //TODO(gsn): Use a TypeID here
488 + id: makeTypeId(typeCounter++),
489 };
490 }
491
@@ -488,7 +503,7 @@ export function typeEquals(tA: Type, tB: Type): boolean {
503
504 function typeVarEquals(tA: Type, tB: Type): boolean {
505 if (tA.kind === "Type" && tB.kind === "Type") {
491 - return tA.name === tB.name;
506 + return tA.id === tB.id;
507 }
508 return false;
509 }
compiler/forget/src/HIR/InferTypes.ts
+18 -17
@@ -3,13 +3,14 @@ import invariant from "invariant";
3 import {
4 HIRFunction,
5 Instruction,
6 + LValue,
7 makeType,
8 + Place,
9 PropType,
10 Type,
11 typeEquals,
12 + TypeId,
13 TypeVar,
11 - Place,
12 - LValue,
14 } from "./HIR";
15 import { eachInstructionOperand } from "./visitors";
16
@@ -210,7 +211,7 @@ function assignTypeForLvalue(
211 );
212 }
213
213 -type Substitution = Map<string, Type>;
214 +type Substitution = Map<TypeId, Type>;
215 class Unifier {
216 substitutions: Substitution = new Map();
217
@@ -231,13 +232,13 @@ class Unifier {
232 }
233
234 bindVariableTo(v: TypeVar, type: Type): void {
234 - if (this.substitutions.has(v.name)) {
235 - this.unify(this.substitutions.get(v.name)!, type);
235 + if (this.substitutions.has(v.id)) {
236 + this.unify(this.substitutions.get(v.id)!, type);
237 return;
238 }
239
239 - if (type.kind === "Type" && this.substitutions.has(type.name)) {
240 - this.unify(v, this.substitutions.get(type.name)!);
240 + if (type.kind === "Type" && this.substitutions.has(type.id)) {
241 + this.unify(v, this.substitutions.get(type.id)!);
242 return;
243 }
244
@@ -250,14 +251,14 @@ class Unifier {
251 throw new Error("cycle detected");
252 }
253
253 - this.substitutions.set(v.name, type);
254 + this.substitutions.set(v.id, type);
255 }
256
257 bindToProp(type: TypeVar, prop: PropType) {
258 let object = prop.objectType;
259
259 - if (object.kind === "Type" && this.substitutions.has(object.name)) {
260 - object = this.substitutions.get(object.name)!;
260 + if (object.kind === "Type" && this.substitutions.has(object.id)) {
261 + object = this.substitutions.get(object.id)!;
262 }
263
264 if (object.kind === "Object") {
@@ -270,14 +271,14 @@ class Unifier {
271 return;
272 }
273
273 - this.substitutions.set(type.name, prop);
274 + this.substitutions.set(type.id, prop);
275 }
276
277 occursCheck(v: TypeVar, type: Type): boolean {
278 if (typeEquals(v, type)) return true;
279
279 - if (type.kind === "Type" && this.substitutions.has(type.name)) {
280 - return this.occursCheck(v, this.substitutions.get(type.name)!);
280 + if (type.kind === "Type" && this.substitutions.has(type.id)) {
281 + return this.occursCheck(v, this.substitutions.get(type.id)!);
282 }
283
284 if (type.kind === "Object") {
@@ -297,8 +298,8 @@ class Unifier {
298 }
299
300 if (type.kind === "Type") {
300 - if (this.substitutions.has(type.name)) {
301 - return this.get(this.substitutions.get(type.name)!);
301 + if (this.substitutions.has(type.id)) {
302 + return this.get(this.substitutions.get(type.id)!);
303 } else {
304 return type;
305 }
@@ -308,8 +309,8 @@ class Unifier {
309 }
310
311 generalize(objectType: Type, name: Array<string> | null): Type | null {
311 - if (objectType.kind === "Type" && this.substitutions.has(objectType.name)) {
312 - objectType = this.substitutions.get(objectType.name)!;
312 + if (objectType.kind === "Type" && this.substitutions.has(objectType.id)) {
313 + objectType = this.substitutions.get(objectType.id)!;
314 }
315
316 if (