@@ -86,17 +86,13 @@ type ErrorOutputContainer struct {
8686
8787type ErrorReporter func (message * diagnostics.Message , args ... any )
8888
89- type RecursionIdKind uint32
90-
91- const (
92- RecursionIdKindNode RecursionIdKind = iota
93- RecursionIdKindSymbol
94- RecursionIdKindType
95- )
96-
9789type RecursionId struct {
98- kind RecursionIdKind
99- id uint32
90+ value any
91+ }
92+
93+ // This function exists to constrain the types of values that can be used as recursion IDs.
94+ func asRecursionId [T * ast.Node | * ast.Symbol | * Type ](value T ) RecursionId {
95+ return RecursionId {value : value }
10096}
10197
10298type Relation struct {
@@ -836,35 +832,35 @@ func getRecursionIdentity(t *Type) RecursionId {
836832 // Deferred type references are tracked through their associated AST node. This gives us finer
837833 // granularity than using their associated target because each manifest type reference has a
838834 // unique AST node.
839- return RecursionId { kind : RecursionIdKindNode , id : uint32 ( ast . GetNodeId ( t .AsTypeReference ().node ))}
835+ return asRecursionId ( t .AsTypeReference ().node )
840836 }
841837 if t .symbol != nil && ! (t .objectFlags & ObjectFlagsAnonymous != 0 && t .symbol .Flags & ast .SymbolFlagsClass != 0 ) {
842838 // We track object types that have a symbol by that symbol (representing the origin of the type), but
843839 // exclude the static side of a class since it shares its symbol with the instance side.
844- return RecursionId { kind : RecursionIdKindSymbol , id : uint32 ( ast . GetSymbolId ( t .symbol ))}
840+ return asRecursionId ( t .symbol )
845841 }
846842 if isTupleType (t ) {
847- return RecursionId { kind : RecursionIdKindType , id : uint32 (t .Target (). id )}
843+ return asRecursionId (t .Target ())
848844 }
849845 }
850846 if t .flags & TypeFlagsTypeParameter != 0 && t .symbol != nil {
851847 // We use the symbol of the type parameter such that all "fresh" instantiations of that type parameter
852848 // have the same recursion identity.
853- return RecursionId { kind : RecursionIdKindSymbol , id : uint32 ( ast . GetSymbolId ( t .symbol ))}
849+ return asRecursionId ( t .symbol )
854850 }
855851 if t .flags & TypeFlagsIndexedAccess != 0 {
856852 // Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P1][P2][P3] it is A.
857853 t = t .AsIndexedAccessType ().objectType
858854 for t .flags & TypeFlagsIndexedAccess != 0 {
859855 t = t .AsIndexedAccessType ().objectType
860856 }
861- return RecursionId { kind : RecursionIdKindType , id : uint32 ( t . id )}
857+ return asRecursionId ( t )
862858 }
863859 if t .flags & TypeFlagsConditional != 0 {
864860 // The root object represents the origin of the conditional type
865- return RecursionId { kind : RecursionIdKindNode , id : uint32 ( ast . GetNodeId ( t .AsConditionalType ().root .node .AsNode ()))}
861+ return asRecursionId ( t .AsConditionalType ().root .node .AsNode ())
866862 }
867- return RecursionId { kind : RecursionIdKindType , id : uint32 ( t . id )}
863+ return asRecursionId ( t )
868864}
869865
870866func (c * Checker ) getBestMatchingType (source * Type , target * Type , isRelatedTo func (source * Type , target * Type ) Ternary ) * Type {
0 commit comments