diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 4264e59128..35d69199c7 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -460,17 +460,32 @@ export type ObjectType = { kind: "Object"; properties: Map }; export type PropType = { kind: "Prop"; objectType: Type; name: string }; export type TypeVar = { kind: "Type"; - name: string; + id: TypeId; }; export type PolyType = { kind: "Poly"; }; +/** + * Simulated opaque type for TypeId to prevent using normal numbers as ids + * accidentally. + */ +const opaqueTypeId = Symbol(); +export type TypeId = number & { [opaqueTypeId]: "IdentifierId" }; + +export function makeTypeId(id: number): TypeId { + invariant( + id >= 0 && Number.isInteger(id), + "Expected instruction id to be a non-negative integer" + ); + return id as TypeId; +} + let typeCounter = 0; export function makeType(): TypeVar { return { kind: "Type", - name: `t${typeCounter++}`, //TODO(gsn): Use a TypeID here + id: makeTypeId(typeCounter++), }; } @@ -488,7 +503,7 @@ export function typeEquals(tA: Type, tB: Type): boolean { function typeVarEquals(tA: Type, tB: Type): boolean { if (tA.kind === "Type" && tB.kind === "Type") { - return tA.name === tB.name; + return tA.id === tB.id; } return false; } diff --git a/compiler/forget/src/HIR/InferTypes.ts b/compiler/forget/src/HIR/InferTypes.ts index 52a42711b7..13fbc48aca 100644 --- a/compiler/forget/src/HIR/InferTypes.ts +++ b/compiler/forget/src/HIR/InferTypes.ts @@ -3,13 +3,14 @@ import invariant from "invariant"; import { HIRFunction, Instruction, + LValue, makeType, + Place, PropType, Type, typeEquals, + TypeId, TypeVar, - Place, - LValue, } from "./HIR"; import { eachInstructionOperand } from "./visitors"; @@ -210,7 +211,7 @@ function assignTypeForLvalue( ); } -type Substitution = Map; +type Substitution = Map; class Unifier { substitutions: Substitution = new Map(); @@ -231,13 +232,13 @@ class Unifier { } bindVariableTo(v: TypeVar, type: Type): void { - if (this.substitutions.has(v.name)) { - this.unify(this.substitutions.get(v.name)!, type); + if (this.substitutions.has(v.id)) { + this.unify(this.substitutions.get(v.id)!, type); return; } - if (type.kind === "Type" && this.substitutions.has(type.name)) { - this.unify(v, this.substitutions.get(type.name)!); + if (type.kind === "Type" && this.substitutions.has(type.id)) { + this.unify(v, this.substitutions.get(type.id)!); return; } @@ -250,14 +251,14 @@ class Unifier { throw new Error("cycle detected"); } - this.substitutions.set(v.name, type); + this.substitutions.set(v.id, type); } bindToProp(type: TypeVar, prop: PropType) { let object = prop.objectType; - if (object.kind === "Type" && this.substitutions.has(object.name)) { - object = this.substitutions.get(object.name)!; + if (object.kind === "Type" && this.substitutions.has(object.id)) { + object = this.substitutions.get(object.id)!; } if (object.kind === "Object") { @@ -270,14 +271,14 @@ class Unifier { return; } - this.substitutions.set(type.name, prop); + this.substitutions.set(type.id, prop); } occursCheck(v: TypeVar, type: Type): boolean { if (typeEquals(v, type)) return true; - if (type.kind === "Type" && this.substitutions.has(type.name)) { - return this.occursCheck(v, this.substitutions.get(type.name)!); + if (type.kind === "Type" && this.substitutions.has(type.id)) { + return this.occursCheck(v, this.substitutions.get(type.id)!); } if (type.kind === "Object") { @@ -297,8 +298,8 @@ class Unifier { } if (type.kind === "Type") { - if (this.substitutions.has(type.name)) { - return this.get(this.substitutions.get(type.name)!); + if (this.substitutions.has(type.id)) { + return this.get(this.substitutions.get(type.id)!); } else { return type; } @@ -308,8 +309,8 @@ class Unifier { } generalize(objectType: Type, name: Array | null): Type | null { - if (objectType.kind === "Type" && this.substitutions.has(objectType.name)) { - objectType = this.substitutions.get(objectType.name)!; + if (objectType.kind === "Type" && this.substitutions.has(objectType.id)) { + objectType = this.substitutions.get(objectType.id)!; } if (