[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 (