pub enum TypeData {
Show 30 variants
Intrinsic(IntrinsicKind),
Literal(LiteralValue),
Object(ObjectShapeId),
ObjectWithIndex(ObjectShapeId),
Union(TypeListId),
Intersection(TypeListId),
Array(TypeId),
Tuple(TupleListId),
Function(FunctionShapeId),
Callable(CallableShapeId),
TypeParameter(TypeParamInfo),
BoundParameter(u32),
Lazy(DefId),
Recursive(u32),
Enum(DefId, TypeId),
Application(TypeApplicationId),
Conditional(ConditionalTypeId),
Mapped(MappedTypeId),
IndexAccess(TypeId, TypeId),
TemplateLiteral(TemplateLiteralId),
TypeQuery(SymbolRef),
KeyOf(TypeId),
ReadonlyType(TypeId),
UniqueSymbol(SymbolRef),
Infer(TypeParamInfo),
ThisType,
StringIntrinsic {
kind: StringIntrinsicKind,
type_arg: TypeId,
},
ModuleNamespace(SymbolRef),
NoInfer(TypeId),
Error,
}Expand description
The structural “shape” of a type.
This is the key used for interning - structurally identical types
will have the same TypeData and therefore the same TypeId.
Variants§
Intrinsic(IntrinsicKind)
Intrinsic types (any, unknown, never, void, null, undefined, boolean, number, string, bigint, symbol, object)
Literal(LiteralValue)
Literal types (“hello”, 42, true, 123n)
Object(ObjectShapeId)
Object type with sorted property list for structural identity
ObjectWithIndex(ObjectShapeId)
Object type with index signatures For objects like { [key: string]: number, foo: string }
Union(TypeListId)
Union type (A | B | C)
Intersection(TypeListId)
Intersection type (A & B & C)
Array(TypeId)
Array type
Tuple(TupleListId)
Tuple type
Function(FunctionShapeId)
Function type
Callable(CallableShapeId)
Callable type with overloaded signatures For interfaces with call/construct signatures
TypeParameter(TypeParamInfo)
Type parameter (generic)
BoundParameter(u32)
Bound type parameter using De Bruijn index for alpha-equivalence.
Represents a type parameter relative to the current binding scope.
Used by the Canonicalizer to achieve alpha-equivalence, where
type F<T> = T and type G<U> = U are considered identical.
§Alpha-Equivalence (Task #32)
When canonicalizing generic types, we replace named type parameters with positional indices to achieve structural identity.
§Example
type F<T> = { value: T }; // canonicalizes to Object({ value: BoundParameter(0) })
type G<U> = { value: U }; // also canonicalizes to Object({ value: BoundParameter(0) })
// Both get the same TypeId because they're structurally identical§De Bruijn Index Semantics
BoundParameter(0)= the most recently bound type parameterBoundParameter(1)= the second-most recently bound type parameterBoundParameter(n)= the (n+1)th-most recently bound type parameter
Lazy(DefId)
Reference to a named type (interface, class, type alias)
Uses SymbolId to break infinite recursion
DEPRECATED: Use Lazy(DefId) for new code. This is kept for backward compatibility
during the migration from SymbolRef to DefId.
PHASE 4.2: REMOVED - Migration complete, all types now use Lazy(DefId)
Lazy reference to a type definition.
Unlike Ref(SymbolRef) which references Binder symbols, Lazy(DefId) uses
Solver-owned identifiers that:
- Don’t require Binder context
- Support content-addressed hashing for LSP stability
- Enable Salsa integration for incremental compilation
The type is evaluated lazily when first accessed, resolving to the actual
type stored in the DefinitionStore.
§Migration
Eventually all Ref(SymbolRef) usages will be replaced with Lazy(DefId).
Recursive(u32)
Recursive type reference using De Bruijn index.
Represents a back-reference to a type N levels up the nesting path. This is used for canonicalizing recursive types to achieve O(1) equality.
§Graph Isomorphism (Task #32)
When canonicalizing recursive type aliases, we replace cycles with relative De Bruijn indices instead of absolute Lazy references.
§Example
type A = { x: A }; // canonicalizes to Object({ x: Recursive(0) })
type B = { x: B }; // also canonicalizes to Object({ x: Recursive(0) })
// Both get the same TypeId because they're structurally identical§De Bruijn Index Semantics
Recursive(0)= the current type itself (immediate recursion)Recursive(1)= one level up (parent in the nesting chain)Recursive(n)= n levels up
§Nominal vs Structural
This is ONLY used for structural types (type aliases). Nominal types (classes, interfaces) preserve their Lazy(DefId) for nominal identity.
Enum(DefId, TypeId)
Enum type with nominal identity and structural member types.
Enums are nominal types - two different enums with the same member types
are NOT compatible (e.g., enum E1 { A, B } is not assignable to enum E2 { A, B }).
DefId: The unique identity of the enum (for E1 vs E2 nominal checking)TypeId: The structural union of member types (e.g., 0 | 1 for numeric enums), used for assignability to primitives (e.g., E1 assignable to number)
Application(TypeApplicationId)
Generic type application (Base
Conditional(ConditionalTypeId)
Conditional type (T extends U ? X : Y)
Mapped(MappedTypeId)
Mapped type ({ [K in Keys]: ValueType })
IndexAccess(TypeId, TypeId)
Index access type (T[K])
TemplateLiteral(TemplateLiteralId)
Template literal type (hello${string}world)
TypeQuery(SymbolRef)
Type query (typeof expression in type position)
KeyOf(TypeId)
KeyOf type operator (keyof T)
ReadonlyType(TypeId)
Readonly type modifier (readonly T[])
UniqueSymbol(SymbolRef)
Unique symbol type
Infer(TypeParamInfo)
Infer type (infer R in conditional types)
ThisType
This type (polymorphic this)
StringIntrinsic
String manipulation intrinsic types
Uppercase
ModuleNamespace(SymbolRef)
Module namespace type (import * as ns from “module”)
Uses SymbolRef for lazy evaluation to avoid circular dependency issues
NoInfer(TypeId)
NoInfer
Error
Error type for recovery
Trait Implementations§
impl Eq for TypeData
impl StructuralPartialEq for TypeData
Auto Trait Implementations§
impl Freeze for TypeData
impl RefUnwindSafe for TypeData
impl Send for TypeData
impl Sync for TypeData
impl Unpin for TypeData
impl UnsafeUnpin for TypeData
impl UnwindSafe for TypeData
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.