@@ -1174,11 +1174,19 @@ export type NonLocalBinding =
11741174
11751175// Represents a user-defined variable (has a name) or a temporary variable (no name).
11761176export type Identifier = {
1177- /*
1178- * unique value to distinguish a variable, since name is not guaranteed to
1179- * exist or be unique
1177+ /**
1178+ * After EnterSSA, `id` uniquely identifies an SSA instance of a variable.
1179+ * Before EnterSSA, `id` matches `declarationId`.
11801180 */
11811181 id : IdentifierId ;
1182+
1183+ /**
1184+ * Uniquely identifies a given variable in the original program. If a value is
1185+ * reassigned in the original program each reassigned value will have a distinct
1186+ * `id` (after EnterSSA), but they will still have the same `declarationId`.
1187+ */
1188+ declarationId : DeclarationId ;
1189+
11821190 // null for temporaries. name is primarily used for debugging.
11831191 name : IdentifierName | null ;
11841192 // The range for which this variable is mutable
@@ -1212,6 +1220,7 @@ export function makeTemporaryIdentifier(
12121220 return {
12131221 id,
12141222 name : null ,
1223+ declarationId : makeDeclarationId ( id ) ,
12151224 mutableRange : { start : makeInstructionId ( 0 ) , end : makeInstructionId ( 0 ) } ,
12161225 scope : null ,
12171226 type : makeType ( ) ,
@@ -1239,6 +1248,9 @@ export function makeIdentifierName(name: string): ValidatedIdentifier {
12391248
12401249/**
12411250 * Given an unnamed identifier, promote it to a named identifier.
1251+ *
1252+ * Note: this uses the identifier's DeclarationId to ensure that all
1253+ * instances of the same declaration will have the same name.
12421254 */
12431255export function promoteTemporary ( identifier : Identifier ) : void {
12441256 CompilerError . invariant ( identifier . name === null , {
@@ -1249,7 +1261,7 @@ export function promoteTemporary(identifier: Identifier): void {
12491261 } ) ;
12501262 identifier . name = {
12511263 kind : 'promoted' ,
1252- value : `#t${ identifier . id } ` ,
1264+ value : `#t${ identifier . declarationId } ` ,
12531265 } ;
12541266}
12551267
@@ -1260,6 +1272,9 @@ export function isPromotedTemporary(name: string): boolean {
12601272/**
12611273 * Given an unnamed identifier, promote it to a named identifier, distinguishing
12621274 * it as a value that needs to be capitalized since it appears in JSX element tag position
1275+ *
1276+ * Note: this uses the identifier's DeclarationId to ensure that all
1277+ * instances of the same declaration will have the same name.
12631278 */
12641279export function promoteTemporaryJsxTag ( identifier : Identifier ) : void {
12651280 CompilerError . invariant ( identifier . name === null , {
@@ -1270,7 +1285,7 @@ export function promoteTemporaryJsxTag(identifier: Identifier): void {
12701285 } ) ;
12711286 identifier . name = {
12721287 kind : 'promoted' ,
1273- value : `#T${ identifier . id } ` ,
1288+ value : `#T${ identifier . declarationId } ` ,
12741289 } ;
12751290}
12761291
@@ -1508,6 +1523,23 @@ export function makeIdentifierId(id: number): IdentifierId {
15081523 return id as IdentifierId ;
15091524}
15101525
1526+ /*
1527+ * Simulated opaque type for IdentifierId to prevent using normal numbers as ids
1528+ * accidentally.
1529+ */
1530+ const opageDeclarationId = Symbol ( ) ;
1531+ export type DeclarationId = number & { [ opageDeclarationId ] : 'DeclarationId' } ;
1532+
1533+ export function makeDeclarationId ( id : number ) : DeclarationId {
1534+ CompilerError . invariant ( id >= 0 && Number . isInteger ( id ) , {
1535+ reason : 'Expected declaration id to be a non-negative integer' ,
1536+ description : null ,
1537+ loc : null ,
1538+ suggestions : null ,
1539+ } ) ;
1540+ return id as DeclarationId ;
1541+ }
1542+
15111543/*
15121544 * Simulated opaque type for InstructionId to prevent using normal numbers as ids
15131545 * accidentally.
0 commit comments