types

package
v0.14.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package types provides cycle detection for type definitions.

This module detects cyclic type references at the AST level, working with type declarations before full type resolution. It handles both simple recursive types (Person → Person) and generic recursive ADTs (List[a] → List[a]).

Package types provides type inference debugging infrastructure.

TypeDebugSink is an orthogonal debug architecture that avoids scattered "if debug { ... }" statements throughout the type checker. Instead, events are emitted to a sink interface, with NoOpDebugSink providing zero overhead in production and VerboseDebugSink collecting events for formatted output.

Usage:

// Production (zero overhead)
tc := NewCoreTypeChecker()
tc.DebugSink = NoOpDebugSink{}

// Debug mode (collects events)
sink := NewVerboseDebugSink()
tc.DebugSink = sink
// ... run type checking ...
for _, event := range sink.Events() {
    fmt.Println(event)
}

Package types provides type report functionality for debugging.

TypeReport is the canonical primitive for type debugging. It consolidates information from multiple data structures (CoreTI, substitution, constraints) into a single queryable API.

Usage:

report := tc.TypeReport(nodeID)
fmt.Printf("Raw: %s, Resolved: %s\n", report.Raw, report.Resolved)

See: design_docs/planned/v0_5_10/m-dx11-type-inference-debugging.md

Package types implements Hindley-Milner type inference for AILANG's Core AST.

CoreTypeInfo Contract (M-DX4)

CoreTypeInfo (CoreTI) is a mapping from Core NodeID to inferred Type. It is the source of truth for type-guided code generation during lowering.

**Contract**:

  • CoreTI is TOTAL for all Core nodes after type checking completes
  • Types may be type variables (TVar) before specialization/monomorphization
  • Lowering of overloaded operators requires non-TVar heads (concrete types)
  • If a Core node has no CoreTI entry, that is a COMPILER BUG

**Phase Requirements**:

  • Pre-monomorphization: CoreTI may contain TVars for polymorphic code (VALID)
  • Post-monomorphization: Specialized bodies should have concrete types
  • Post-VarResolution (v0.3.18+): Monomorphic Var nodes get concrete types
  • Lowering phase: Operators need concrete heads; TVars trigger fallback

**Validation**:

  • ValidateCoreTypeInfo (internal/pipeline) checks 100% coverage before lowering
  • Validation accepts TVars as valid (checks presence, not concreteness)
  • Use --debug-compile flag to see telemetry of CoreTI hits/misses during lowering

**Why TVars Remain After Type Inference (v0.3.18)**:

After Hindley-Milner unification and ApplySubstitution, some Var nodes may still have TVars in CoreTI. This happens because:

  1. Let-bound variables: The substitution tracks Let bindings but doesn't always resolve Var references to their binding's concrete type
  2. Polymorphic preservation: Lambda parameters intentionally keep TVars until call-site specialization (M-POLY-B)

The VarResolver (internal/pipeline/resolve_vars.go) is a WORKAROUND that propagates monomorphic types from Let bindings to Var usages. It only propagates concrete types (Int, Float, String, Bool, List) and preserves polymorphism for lambda params.

**Future (M-POLY-B, v0.4.1+)**: Var-bound polymorphic lambdas will be re-elaborated after monomorphization, which will naturally resolve all operator types in specialized bodies. The VarResolver is a pragmatic bridge until then.

**Debug**:

  • ailang debug ast <file> --show-types --compact: Inspect CoreTI for a file
  • ailang run --debug-compile <file>: See lowering telemetry (CoreTI coverage)
  • Look for "Var type resolution complete" in debug output

See: design_docs/planned/v0_3_18/M-DX4-SPRINT-PLAN.md

Package types implements AILANG's type system.

String() Contract

Type.String() is for DIAGNOSTIC output ONLY. It may truncate on:

  • Deeply nested types (>100 levels)
  • Cyclic types (mu-types, recursive ADTs)

No algorithmic logic may depend on String() output. For structural operations, use:

  • types.Equal(a, b) for equality
  • traverse.CollectFreeVars(t) for variable collection
  • traverse.Occurs(name, t) for occurs check

For safe stringification that handles cycles, use SafeTypeString().

Index

Constants

View Source
const (
	TC_REC_001 = "TC_REC_001" // Missing field
	TC_REC_002 = "TC_REC_002" // Duplicate field in literal
	TC_REC_003 = "TC_REC_003" // Row occurs check
	TC_REC_004 = "TC_REC_004" // Field type mismatch
)

Record-specific error codes (M-R5 Day 3.3)

View Source
const MaxStringifyDepth = 100

MaxStringifyDepth is the maximum depth for type stringification. Beyond this, types are truncated with "..." to prevent hangs on cyclic types.

Variables

View Source
var (
	Star      = KStar{}
	Effect    = KEffect{}
	Record    = KRecord{}
	EffectRow = KRow{ElemKind: Effect}
	RecordRow = KRow{ElemKind: Record}
)

Common kinds

View Source
var (
	TInt    = &TCon{Name: "int"}
	TFloat  = &TCon{Name: "float"}
	TString = &TCon{Name: "string"}
	TBool   = &TCon{Name: "bool"}
	TUnit   = &TCon{Name: "()"}
	TBytes  = &TCon{Name: "bytes"}
)

Common predefined types

View Source
var (
	EffectIO    = &SimpleEffect{Name: "IO"}
	EffectFS    = &SimpleEffect{Name: "FS"}
	EffectNet   = &SimpleEffect{Name: "Net"}
	EffectDB    = &SimpleEffect{Name: "DB"}
	EffectRand  = &SimpleEffect{Name: "Rand"}
	EffectClock = &SimpleEffect{Name: "Clock"}
	EffectTrace = &SimpleEffect{Name: "Trace"}
	EffectAsync = &SimpleEffect{Name: "Async"}
)

Common effects

Functions

func CanonKey

func CanonKey(namespace, className string, typ Type, method string) string

CanonKey is an alias for MakeDictionaryKey - the single entry point for all dictionary key generation to ensure consistency across linker and evaluator.

func EffectRowDifference

func EffectRowDifference(a, b *Row) []string

EffectRowDifference returns the effects in 'a' that are not in 'b' Result is sorted alphabetically

func ExtractTVarName

func ExtractTVarName(t Type) (string, bool)

ExtractTVarName extracts the name from a type variable. Returns (name, true) if the type is TVar or TVar2, ("", false) otherwise.

This helper prevents silent failures when pattern matching on type variables. Use this instead of checking *TVar and *TVar2 separately.

Example:

if name, ok := types.ExtractTVarName(paramType); ok {
    // paramType is a type variable with name
} else {
    // paramType is not a type variable
}

func FormatDefaultingTraces

func FormatDefaultingTraces(traces []DefaultingTrace) string

FormatDefaultingTraces creates a human-readable summary of defaulting decisions

func FormatEffectRow

func FormatEffectRow(row *Row) string

FormatEffectRow formats an effect row for display Returns "! {IO, FS}" for non-empty rows, "" for pure (nil) Includes budget annotations when present: "! {IO @limit=5, FS}"

func IsGroundType

func IsGroundType(t Type) bool

IsGroundType checks if a type contains no type variables This is used to verify that types are fully resolved before elaboration

func IsKnownEffect

func IsKnownEffect(name string) bool

IsKnownEffect checks if an effect name is one of the canonical effects

func IsOpenRecord

func IsOpenRecord(rec Type) bool

IsOpenRecord checks if a record type is open (has row variable)

func IsTVar

func IsTVar(t Type) bool

IsTVar checks if a type is a type variable (TVar or TVar2). Returns true if the type is TVar or TVar2, false otherwise.

Example:

if types.IsTVar(paramType) {
    // paramType is polymorphic
}

func MakeDictionaryKey

func MakeDictionaryKey(namespace, className string, typ Type, method string) string

MakeDictionaryKey creates a deterministic registry key for a dictionary Format: <namespace>::<ClassName>::<TypeNF>::<method> Example: "prelude::Num::Int::add"

func MarshalCoreTypeInfo

func MarshalCoreTypeInfo(cti CoreTypeInfo) ([]byte, error)

MarshalCoreTypeInfo serializes a CoreTypeInfo (map[uint64]Type) to JSON.

func MarshalKind

func MarshalKind(k Kind) ([]byte, error)

MarshalKind serializes a Kind to JSON.

func MarshalScheme

func MarshalScheme(s *Scheme) ([]byte, error)

MarshalScheme serializes a Scheme to JSON.

func NormalizeTypeName

func NormalizeTypeName(t Type) string

NormalizeTypeName produces a canonical string representation of a type for use in deterministic registry keys and pretty-printing. Examples:

  • int → "Int"
  • float → "Float"
  • [int] → "List<Int>"
  • (int, float) → "Tuple<Int,Float>"
  • {x: int, y: float} → "Record<x:Int,y:Float>"

Design decision: We use angle brackets <> for type parameters and Tuple<T1,T2> (not Pair) for consistency across all parameterized types.

func OperatorMethod

func OperatorMethod(op string, isUnary bool) string

OperatorMethod returns the method name for an operator. Exported for use by the elaborator during dictionary-passing transformation. Binary operators map to their corresponding type class methods. Unary minus is handled as "neg" (negate) method in the Num class.

func ParseDictionaryKey

func ParseDictionaryKey(key string) (namespace, className, typeNF, method string, err error)

ParseDictionaryKey extracts components from a dictionary key Now uses :: separator for better visual clarity

func RecordHasField

func RecordHasField(rec Type, field string) bool

RecordHasField checks if a record type has a specific field

func SafeEquals

func SafeEquals(t1, t2 Type) bool

SafeEquals compares two types for equality with cycle detection This prevents infinite loops when comparing cyclic type graphs

func SafeTypeString

func SafeTypeString(t Type) string

SafeTypeString returns a string representation of a type with depth limiting. If the depth exceeds MaxStringifyDepth, returns a truncated representation. This prevents infinite loops on cyclic type graphs.

func SetBuiltinEnvFactory

func SetBuiltinEnvFactory(factory func() *TypeEnv)

SetBuiltinEnvFactory allows the link package to provide the builtin env implementation

func SubsumeEffectRows

func SubsumeEffectRows(a, b *Row) bool

SubsumeEffectRows checks if effect row 'a' is subsumed by effect row 'b' Returns true if all effects in 'a' are present in 'b' Pure (nil) is subsumed by anything

func TruncatedTypeString

func TruncatedTypeString(t Type, maxLen int) string

TruncatedTypeString returns a string representation that's guaranteed to be short. Useful for error messages and logging where space is limited.

func TypeCheckFile

func TypeCheckFile(filename string, program *ast.Program) error

TypeCheckFile is a convenience function to type check a file

Types

type Builder

type Builder struct{}

Builder provides a fluent API for constructing type signatures This eliminates the need for verbose nested struct literals and provides:

  • Readable, self-documenting type construction
  • Compile-time safety (wrong field name = compile error)
  • Future-proofing for polymorphism and row types

Example usage:

T := NewBuilder()
httpReqType := T.Func(
    T.String(), T.String(),
    T.List(T.Record(Field("name", T.String()), Field("value", T.String()))),
    T.String(),
).Returns(
    T.App("Result", responseType, T.Con("NetError")),
).Effects("Net")

func NewBuilder

func NewBuilder() *Builder

NewBuilder creates a new type builder

func (*Builder) App

func (b *Builder) App(con string, args ...Type) Type

App creates a type application (e.g., List<String>, Result<T, E>) For higher-kinded types like Result<Response, NetError>

func (*Builder) Bool

func (b *Builder) Bool() Type

Bool returns the bool type

func (*Builder) Bytes

func (b *Builder) Bytes() Type

Bytes returns the bytes type

func (*Builder) Con

func (b *Builder) Con(name string) Type

Con creates a type constructor (e.g., "Result", "Option", "List")

func (*Builder) Float

func (b *Builder) Float() Type

Float returns the float type

func (*Builder) Func

func (b *Builder) Func(params ...Type) *FuncBuilder

Func starts building a function type Takes the parameter types as arguments

Example:

T.Func(T.String(), T.Int()).Returns(T.Bool())

func (*Builder) Int

func (b *Builder) Int() Type

Int returns the int type

func (*Builder) List

func (b *Builder) List(elem Type) Type

List creates a list type: list[T] Uses lowercase "list" to match AILANG syntax

func (*Builder) Map

func (b *Builder) Map(key, val Type) Type

Map creates a map type: Map[K, V]

func (*Builder) Rec

func (b *Builder) Rec(pairs ...interface{}) Type

Rec creates a record type with alternating key-value pairs This is a convenience method for simple records

Example:

T.Rec("name", T.String(), "age", T.Int())

func (*Builder) Record

func (b *Builder) Record(fields ...FieldSpec) Type

Record creates a record type with the given fields Duplicate field names will panic at build time

Example:

T.Record(
    Field("name", T.String()),
    Field("age", T.Int()),
)

func (*Builder) String

func (b *Builder) String() Type

String returns the string type

func (*Builder) Unit

func (b *Builder) Unit() Type

Unit returns the unit type ()

func (*Builder) Var

func (b *Builder) Var(name string) Type

Var creates a type variable (e.g., 'a', 'b') Used for polymorphic types like: forall a. a -> a

type ClassConstraint

type ClassConstraint struct {
	Class  string
	Type   Type
	Path   []string
	NodeID uint64 // NodeID of the Core expression that generated this constraint
}

ClassConstraint represents a type class constraint

func (ClassConstraint) String

func (c ClassConstraint) String() string

type ClassInstance

type ClassInstance struct {
	ClassName string   // e.g., "Num", "Ord", "Eq"
	TypeHead  Type     // Monomorphic type for v1 (TInt, TFloat, etc.)
	Dict      Dict     // Method implementations
	Super     []string // Superclasses this instance provides (e.g., Ord provides Eq)
}

ClassInstance represents a type class instance with its methods

type Constraint

type Constraint struct {
	Class string
	Type  Type
}

Constraint represents a type class constraint

func (*Constraint) String

func (c *Constraint) String() string

type ConstraintRef

type ConstraintRef struct {
	ClassName string // "Num", "Eq", "Ord", etc.
	Type      Type   // The type involved in the constraint
	NodeID    uint64 // Node where constraint was introduced
	Resolved  bool   // Whether the constraint has been resolved
	Method    string // Method name if resolved (e.g., "add", "eq")
}

ConstraintRef holds a reference to a constraint with source information.

type CoreTypeChecker

type CoreTypeChecker struct {
	CoreTI CoreTypeInfo // Core NodeID → inferred types (principal types for lowering)

	// M-DX11: Debug sink for type inference events
	DebugSink TypeDebugSink
	// contains filtered or unexported fields
}

CoreTypeChecker type checks Core AST and produces TypedAST

func NewCoreTypeChecker

func NewCoreTypeChecker() *CoreTypeChecker

NewCoreTypeChecker creates a new Core type checker

func NewCoreTypeCheckerWithInstances

func NewCoreTypeCheckerWithInstances(instances *InstanceEnv) *CoreTypeChecker

NewCoreTypeCheckerWithInstances creates a type checker with preloaded instances

func (*CoreTypeChecker) ApplySubstEverywhere

func (tc *CoreTypeChecker) ApplySubstEverywhere(
	sub Substitution,
	monotype Type,
	constraints []ClassConstraint,
	typedNode typedast.TypedNode,
	envEntry interface{},
	bindingName string,
) (Type, []ClassConstraint, typedast.TypedNode, interface{})

ApplySubstEverywhere applies substitution coherently to all relevant data structures

func (*CoreTypeChecker) CheckCoreExpr

func (tc *CoreTypeChecker) CheckCoreExpr(expr core.CoreExpr, env *TypeEnv) (typedast.TypedNode, *TypeEnv, error)

CheckCoreExpr type checks a Core expression (exported for testing)

func (*CoreTypeChecker) CheckCoreProgram

func (tc *CoreTypeChecker) CheckCoreProgram(prog *core.Program) (*typedast.TypedProgram, error)

CheckCoreProgram type checks a Core program and produces TypedAST

func (*CoreTypeChecker) DumpInstantiations

func (tc *CoreTypeChecker) DumpInstantiations() map[string]interface{}

DumpInstantiations returns a JSON-serializable map of instantiations

func (*CoreTypeChecker) EnableInstantiationTracking

func (tc *CoreTypeChecker) EnableInstantiationTracking()

EnableInstantiationTracking turns on tracking of polymorphic instantiations

func (*CoreTypeChecker) EnableTraceDefaulting

func (tc *CoreTypeChecker) EnableTraceDefaulting(enable bool)

EnableTraceDefaulting enables defaulting trace output

func (*CoreTypeChecker) FillOperatorMethods

func (tc *CoreTypeChecker) FillOperatorMethods(expr core.CoreExpr)

FillOperatorMethods fills in the Method field for resolved constraints by traversing the Core AST and matching NodeIDs (exported for REPL)

func (*CoreTypeChecker) FinalizeSubstitutions

func (tc *CoreTypeChecker) FinalizeSubstitutions()

FinalizeSubstitutions applies all accumulated defaulting substitutions to CoreTI in a single pass. Must be called after type inference completes, before operator lowering. M-PERF-DOCPARSE: This replaces per-let-binding CoreTI traversals with one final pass.

func (*CoreTypeChecker) GetAliasEnv

func (tc *CoreTypeChecker) GetAliasEnv() map[string]Type

GetAliasEnv returns the type alias environment for use in unification M-BUGFIX: Used to create UnifierWithAliases

func (*CoreTypeChecker) GetResolvedConstraints

func (tc *CoreTypeChecker) GetResolvedConstraints() map[uint64]*ResolvedConstraint

GetResolvedConstraints returns the map of resolved constraints Used by the elaborator for dictionary passing transformation

func (*CoreTypeChecker) InferWithConstraints

func (tc *CoreTypeChecker) InferWithConstraints(expr core.CoreExpr, env *TypeEnv) (typedast.TypedNode, *TypeEnv, Type, []Constraint, error)

InferWithConstraints infers type with constraints for a Core expression Returns: typed expression, updated env, qualified type, constraints, error

func (*CoreTypeChecker) RegisterADTTypeParams

func (tc *CoreTypeChecker) RegisterADTTypeParams(typeName string, paramCount int)

RegisterADTTypeParams registers a single ADT → type param count mapping. M-TAPP-FIX: Used to generate proper TApp types in pattern matching.

func (*CoreTypeChecker) RegisterConstructorType

func (tc *CoreTypeChecker) RegisterConstructorType(ctorName, typeName string)

RegisterConstructorType registers a single constructor → ADT type mapping. M-DX25.4: Used to infer correct types for pattern matching on ADTs.

func (*CoreTypeChecker) RegisterTypeAlias

func (tc *CoreTypeChecker) RegisterTypeAlias(name string, target Type)

RegisterTypeAlias registers a type alias for expansion during unification M-BUGFIX: This allows `type Coord = {x: int, y: int}` to work with ADT variants

func (*CoreTypeChecker) SetADTTypeParams

func (tc *CoreTypeChecker) SetADTTypeParams(params map[string]int)

SetADTTypeParams sets the ADT type → number of type parameters mapping. M-TAPP-FIX: Used to generate proper TApp types in pattern matching.

func (*CoreTypeChecker) SetConstructorTypes

func (tc *CoreTypeChecker) SetConstructorTypes(ctors map[string]string)

SetConstructorTypes sets the constructor → ADT type mappings. M-DX25.4: Used to infer correct types for pattern matching on ADTs.

func (*CoreTypeChecker) SetDebugMode

func (tc *CoreTypeChecker) SetDebugMode(debug bool)

SetDebugMode enables debug output for defaulting traces

func (*CoreTypeChecker) SetDebugSink

func (tc *CoreTypeChecker) SetDebugSink(sink TypeDebugSink)

SetDebugSink sets the debug sink for type inference events. Pass a VerboseDebugSink to collect events for later formatting.

func (*CoreTypeChecker) SetDefaultingConfig

func (tc *CoreTypeChecker) SetDefaultingConfig(config *DefaultingConfig)

SetDefaultingConfig sets a custom defaulting configuration

func (*CoreTypeChecker) SetEffectAnnotations

func (tc *CoreTypeChecker) SetEffectAnnotations(annots map[uint64][]string)

SetEffectAnnotations sets effect annotations from elaboration

func (*CoreTypeChecker) SetEffectAnnotationsFull

func (tc *CoreTypeChecker) SetEffectAnnotationsFull(annots map[uint64][]ast.EffectAnnotation)

SetEffectAnnotationsFull sets full effect annotations with budgets from elaboration M-CAPABILITY-BUDGETS: This preserves @limit=N budget annotations through elaboration

func (*CoreTypeChecker) SetGlobalType

func (tc *CoreTypeChecker) SetGlobalType(key string, scheme *Scheme)

SetGlobalType sets a single global type scheme

func (*CoreTypeChecker) SetGlobalTypes

func (tc *CoreTypeChecker) SetGlobalTypes(types map[string]*Scheme)

SetGlobalTypes sets the global types for import resolution

func (*CoreTypeChecker) SetParamTypeAnnotations

func (tc *CoreTypeChecker) SetParamTypeAnnotations(annots map[uint64][]Type)

SetParamTypeAnnotations sets parameter type annotations from elaboration M-FIX-FLOAT-OP: This preserves float parameter annotations through elaboration

func (*CoreTypeChecker) SetReturnTypeAnnotations

func (tc *CoreTypeChecker) SetReturnTypeAnnotations(annots map[uint64]Type)

SetReturnTypeAnnotations sets return type annotations from elaboration M-FIX-FLOAT-OP: This ensures PI() -> float ACTUALLY constrains inference to return float

func (*CoreTypeChecker) TypeReport

func (tc *CoreTypeChecker) TypeReport(nodeID uint64) TypeReport

TypeReport returns consolidated type information for a Core node. This is the canonical primitive for type debugging, consolidating info from CoreTI, substitution, and resolved constraints.

The report includes:

  • Raw: The type as stored in CoreTI (may contain type variables)
  • Resolved: The type after applying the full substitution closure
  • Constraints: Any class constraints mentioning this node's type variables
  • Origins: Provenance chain showing where the type came from (if debug enabled)
  • Found: Whether the node exists in CoreTI

type CoreTypeInfo

type CoreTypeInfo map[uint64]Type

CoreTypeInfo maps Core expression NodeIDs to their inferred types (principal types after generalization) This is populated during Core type checking and used during operator lowering

func NewCoreTypeInfo

func NewCoreTypeInfo() CoreTypeInfo

NewCoreTypeInfo creates a new CoreTypeInfo map

func UnmarshalCoreTypeInfo

func UnmarshalCoreTypeInfo(data []byte) (CoreTypeInfo, error)

UnmarshalCoreTypeInfo deserializes a CoreTypeInfo from JSON.

func (CoreTypeInfo) ApplySubstitution

func (cti CoreTypeInfo) ApplySubstitution(sub Substitution)

ApplySubstitution applies a type substitution to all entries in CoreTypeInfo This is critical for fixing the CoreTI population gaps bug (M-DX4): After defaulting resolves type variables (e.g., t1 → Float), we must update CoreTypeInfo with the concrete types, not leave them as type variables.

Note: Substitutions may form chains (e.g., α37 → α38 → float). We repeatedly apply the substitution until we reach a fixed point to fully resolve chains.

func (CoreTypeInfo) Get

func (cti CoreTypeInfo) Get(nodeID uint64) (Type, bool)

Get returns the type for the given Core NodeID and a boolean indicating if it was found

func (CoreTypeInfo) GetForExpr

func (cti CoreTypeInfo) GetForExpr(expr core.CoreExpr) (Type, bool)

GetForExpr is a convenience method to get the type for a Core expression

func (CoreTypeInfo) Has

func (cti CoreTypeInfo) Has(nodeID uint64) bool

Has checks if a type exists for the given Core NodeID

func (CoreTypeInfo) Must

func (cti CoreTypeInfo) Must(nodeID uint64) Type

Must returns the type for the given Core NodeID, or panics with a helpful error if not found

func (CoreTypeInfo) MustForExpr

func (cti CoreTypeInfo) MustForExpr(expr core.CoreExpr) Type

MustForExpr is a convenience method that panics if the type is not found

func (CoreTypeInfo) Set

func (cti CoreTypeInfo) Set(nodeID uint64, t Type)

Set stores a type for the given Core NodeID

type CycleInfo

type CycleInfo struct {
	Kind     CycleKind // Expected or suspicious
	TypeName string    // The type that has a cycle
	Path     []string  // The path through fields that creates the cycle
	Depth    int       // Number of nodes in the cycle
	Note     string    // Optional explanation
}

CycleInfo holds information about a detected cyclic type reference.

func DetectCycles

func DetectCycles(decls []ast.Node, filename string) []CycleInfo

DetectCycles analyzes AST type declarations and returns any cyclic references. It handles both direct self-references and references through type applications.

type CycleKind

type CycleKind string

CycleKind classifies whether a cycle is expected or suspicious.

const (
	// CycleExpected marks cycles that are standard recursive ADT patterns.
	// These include List, Tree, and other common recursive type names,
	// as well as anything in the stdlib.
	CycleExpected CycleKind = "expected"

	// CycleSuspicious marks cycles that may cause traversal issues
	// if not handled with cycle-safe code.
	CycleSuspicious CycleKind = "suspicious"
)

type DebugEvent

type DebugEvent struct {
	Kind      DebugEventKind
	NodeID    uint64
	TypeVar   Type   // For fresh/substitute/default events (typically *TVar2)
	Left      Type   // For unify events
	Right     Type   // For unify events
	Result    Type   // For unify events, or resolved type for substitute
	Defaulted Type   // For default events
	Reason    string // For default events
	ClassName string // For constraint events
	Method    string // For constraint resolve events
	Origin    OriginKind
}

DebugEvent captures a single type inference event for later formatting.

type DebugEventKind

type DebugEventKind int

DebugEventKind identifies the type of debug event.

const (
	EventFreshTypeVar DebugEventKind = iota
	EventUnify
	EventSubstitute
	EventDefault
	EventConstraintAdd
	EventConstraintResolve
)

func (DebugEventKind) String

func (k DebugEventKind) String() string

String returns a human-readable name for the event kind.

type DefaultingConfig

type DefaultingConfig struct {
	Enabled  bool              // Whether defaulting is enabled
	Defaults map[string]Type   // Class -> default type mapping
	Traces   []DefaultingTrace // Record of defaulting decisions
}

DefaultingConfig controls numeric literal defaulting

func DisableDefaulting

func DisableDefaulting() *DefaultingConfig

DisableDefaulting creates a config with defaulting disabled

func GetModuleDefaults

func GetModuleDefaults(moduleName string) *DefaultingConfig

GetModuleDefaults retrieves defaulting config for a specific module

func NewDefaultingConfig

func NewDefaultingConfig() *DefaultingConfig

NewDefaultingConfig creates a standard defaulting configuration

type DefaultingTrace

type DefaultingTrace struct {
	TypeVar   string // The type variable being defaulted
	ClassName string // The class constraint (Num, Fractional, etc.)
	Default   Type   // The chosen default type
	Location  string // Source location
}

DefaultingTrace records when numeric defaulting occurs

type DerivedADTEquality

type DerivedADTEquality struct {
	TypeName string // The ADT type name (e.g., "Color")
}

DerivedADTEquality is a marker type indicating that equality should be synthesized for an ADT with `deriving (Eq)`. The evaluator will handle this specially by comparing TaggedValue instances structurally. M-DX19: Auto-derive Eq for ADT types

type Dict

type Dict = map[string]string // Method name -> implementation identifier

Dict represents method implementations for a type class instance For now, we store method names - actual implementations will be in evaluator

type DictParam

type DictParam struct {
	Name      string // e.g., "dict_Num_α"
	ClassName string // e.g., "Num"
	Type      Type   // e.g., TVar("α")
}

DictParam represents a dictionary parameter in a qualified type

func CanonicalDictParams

func CanonicalDictParams(constraints []ClassConstraint) []DictParam

CanonicalDictParams creates deterministically ordered dictionary parameters

type DictionaryEntry

type DictionaryEntry struct {
	ClassName string
	TypeName  string // Normalized type name
	Method    string
	Impl      interface{} // The actual implementation
}

DictionaryEntry represents a method implementation in a dictionary

type DictionaryRegistry

type DictionaryRegistry struct {
	// contains filtered or unexported fields
}

DictionaryRegistry manages type class dictionaries for all instances. Keys are in the format: "namespace::ClassName::TypeNF::method" Example: "prelude::Num::Int::add"

func NewDictionaryRegistry

func NewDictionaryRegistry() *DictionaryRegistry

NewDictionaryRegistry creates a new registry with built-in instances

func (*DictionaryRegistry) Lookup

func (r *DictionaryRegistry) Lookup(key string) (DictionaryEntry, bool)

Lookup retrieves a dictionary entry by key

func (*DictionaryRegistry) LookupMethod

func (r *DictionaryRegistry) LookupMethod(namespace, className string, typ Type, method string) (interface{}, bool)

LookupMethod retrieves a specific method implementation

func (*DictionaryRegistry) Register

func (r *DictionaryRegistry) Register(namespace, className, typeName, method string, impl interface{})

Register adds a dictionary entry to the registry

func (*DictionaryRegistry) RegisterDerivedEq

func (r *DictionaryRegistry) RegisterDerivedEq(typeName string)

RegisterDerivedEq registers Eq instance for an ADT type with `deriving (Eq)`. The implementation is a marker (DerivedADTEquality) that tells the evaluator to synthesize structural equality comparison for TaggedValue instances. M-DX19: Auto-derive Eq for ADT types

func (*DictionaryRegistry) RegisterInstance

func (r *DictionaryRegistry) RegisterInstance(key string, dict interface{})

RegisterInstance registers a complete type class instance

func (*DictionaryRegistry) ValidateRegistry

func (r *DictionaryRegistry) ValidateRegistry() error

ValidateRegistry checks that all required methods are present for each type class instance

type EffectRowOld

type EffectRowOld struct {
	Effects []EffectType
	Row     *EffectVar // Row variable for extensibility
}

EffectRowOld represents a row of effects (for row polymorphism) - DEPRECATED

func (*EffectRowOld) Equals

func (e *EffectRowOld) Equals(other EffectType) bool

func (*EffectRowOld) String

func (e *EffectRowOld) String() string

type EffectType

type EffectType interface {
	String() string
	Equals(EffectType) bool
}

EffectType represents an effect

type EffectVar

type EffectVar struct {
	Name string
}

EffectVar represents an effect variable

func NewEffectVar

func NewEffectVar() *EffectVar

NewEffectVar creates a fresh effect variable

func (*EffectVar) Equals

func (e *EffectVar) Equals(other EffectType) bool

func (*EffectVar) String

func (e *EffectVar) String() string

type ErrorList

type ErrorList []*TypeCheckError

ErrorList represents multiple type errors

func (ErrorList) Error

func (e ErrorList) Error() string

type FieldSpec

type FieldSpec struct {
	Name string
	Type Type
}

FieldSpec represents a record field specification

func Field

func Field(name string, typ Type) FieldSpec

Field creates a record field specification Used with Record() builder

type FuncBuilder

type FuncBuilder struct {
	// contains filtered or unexported fields
}

FuncBuilder provides a fluent interface for building function types

func (*FuncBuilder) Build

func (fb *FuncBuilder) Build() Type

Build constructs the final function type Usually not needed as Effects() automatically builds

func (*FuncBuilder) Effects

func (fb *FuncBuilder) Effects(eff ...string) Type

Effects adds effect annotations and builds the function type Multiple effects can be specified. Returns the final Type.

Example:

typ := T.Func(T.String()).Returns(T.Unit()).Effects("IO", "Net")

func (*FuncBuilder) Returns

func (fb *FuncBuilder) Returns(ret Type) *FuncBuilder

Returns sets the return type of the function This is required before calling Effects() or Build()

func (*FuncBuilder) RowTail

func (fb *FuncBuilder) RowTail(tailVar string) *FuncBuilder

RowTail adds a row variable tail for effect row polymorphism This is for future extensibility

Example:

typ := T.Func(T.String()).Returns(T.Unit()).RowTail("ρ").Effects("IO")

type InferenceContext

type InferenceContext struct {
	TypeInfo TypeInfo // Maps Surface AST expressions to their inferred types (principal types)
	// contains filtered or unexported fields
}

InferenceContext maintains state during type inference

func NewInferenceContext

func NewInferenceContext() *InferenceContext

NewInferenceContext creates a new inference context

func (*InferenceContext) Infer

func (ctx *InferenceContext) Infer(expr ast.Expr) (Type, *Row, error)

Infer performs type inference on an expression

func (*InferenceContext) SetDebugSink

func (ctx *InferenceContext) SetDebugSink(sink TypeDebugSink)

SetDebugSink sets the debug sink for provenance tracking. This should be called before type inference begins. M-DX11-PHASE2: Also wires the sink to the Unifier for OnSubstitute events.

func (*InferenceContext) SetEnv

func (ctx *InferenceContext) SetEnv(env *TypeEnv)

SetEnv sets the type environment for the inference context

func (*InferenceContext) SolveConstraints

func (ctx *InferenceContext) SolveConstraints() (Substitution, []ClassConstraint, error)

SolveConstraints solves all collected constraints

type Instance

type Instance struct {
	ClassName string
	Type      Type
	Methods   map[string]Type
}

Instance represents a type class instance

type InstanceEnv

type InstanceEnv struct {
	// contains filtered or unexported fields
}

InstanceEnv manages type class instances with coherence checking

func LoadBuiltinInstances

func LoadBuiltinInstances() *InstanceEnv

LoadBuiltinInstances creates the standard set of built-in instances These would normally come from "import std/prelude"

func NewInstanceEnv

func NewInstanceEnv() *InstanceEnv

NewInstanceEnv creates a new empty instance environment

func (*InstanceEnv) Add

func (env *InstanceEnv) Add(inst *ClassInstance) error

Add adds an instance to the environment with coherence checking

func (*InstanceEnv) AddDerivedEqForADT

func (env *InstanceEnv) AddDerivedEqForADT(typeName string) error

AddDerivedEqForADT registers an Eq instance for an ADT type with `deriving (Eq)`. M-DX19: This enables the type checker to resolve Eq constraints for the ADT type.

func (*InstanceEnv) DefaultFor

func (env *InstanceEnv) DefaultFor(class string) Type

DefaultFor returns the default type for a class (for numeric literal defaulting)

func (*InstanceEnv) GetDefault

func (env *InstanceEnv) GetDefault(class string) Type

GetDefault gets the default type for a class

func (*InstanceEnv) Lookup

func (env *InstanceEnv) Lookup(class string, typ Type) (*ClassInstance, error)

Lookup finds an instance, including superclass derivation

func (*InstanceEnv) SetDefault

func (env *InstanceEnv) SetDefault(class string, typ Type)

SetDefault sets the default type for a class

type Instantiation

type Instantiation struct {
	Location     string   // File position "line:col"
	VarName      string   // Variable name
	FreshVars    []string // Fresh type variables generated
	Instantiated Type     // The instantiated monotype
}

Instantiation records a polymorphic type instantiation for debugging

type KEffect

type KEffect struct{}

KEffect represents the kind of effects

func (KEffect) Equals

func (k KEffect) Equals(other Kind) bool

func (KEffect) String

func (k KEffect) String() string

type KRecord

type KRecord struct{}

KRecord represents the kind of record labels

func (KRecord) Equals

func (k KRecord) Equals(other Kind) bool

func (KRecord) String

func (k KRecord) String() string

type KRow

type KRow struct {
	ElemKind Kind
}

KRow represents the kind of rows (Row k)

func (KRow) Equals

func (k KRow) Equals(other Kind) bool

func (KRow) String

func (k KRow) String() string

type KStar

type KStar struct{}

KStar represents the kind of types (* in type theory)

func (KStar) Equals

func (k KStar) Equals(other Kind) bool

func (KStar) String

func (k KStar) String() string

type Kind

type Kind interface {
	String() string
	Equals(Kind) bool
	// contains filtered or unexported methods
}

Kind represents kinds in the type system

func ExtractTVarKind

func ExtractTVarKind(t Type) (Kind, bool)

ExtractTVarKind extracts the kind from a type variable. Returns (kind, true) if the type is TVar2, (nil, false) otherwise.

Note: TVar (v1) does not have a Kind field, only TVar2 does.

Example:

if kind, ok := types.ExtractTVarKind(paramType); ok {
    // paramType is TVar2 with kind
}

func GetKind

func GetKind(t Type) Kind

GetKind returns the kind of any type

func UnmarshalKind

func UnmarshalKind(data []byte) (Kind, error)

UnmarshalKind deserializes a Kind from JSON.

type MissingInstanceError

type MissingInstanceError struct {
	Class string
	Type  Type
	Hint  string
}

MissingInstanceError represents a missing type class instance

func (*MissingInstanceError) Error

func (e *MissingInstanceError) Error() string

type ModuleScopedDefaults

type ModuleScopedDefaults struct {
	ModuleName string
	Config     *DefaultingConfig
}

ModuleScopedDefaults allows per-module defaulting configuration

type NoOpDebugSink

type NoOpDebugSink struct{}

NoOpDebugSink is a debug sink that does nothing. It provides zero overhead in production - all methods are empty and inlined.

func (NoOpDebugSink) OnConstraintAdd

func (NoOpDebugSink) OnConstraintAdd(string, Type, uint64)

func (NoOpDebugSink) OnConstraintResolve

func (NoOpDebugSink) OnConstraintResolve(string, Type, string, uint64)

func (NoOpDebugSink) OnDefault

func (NoOpDebugSink) OnDefault(Type, Type, string)

func (NoOpDebugSink) OnFreshTypeVar

func (NoOpDebugSink) OnFreshTypeVar(Type, uint64, OriginKind)

func (NoOpDebugSink) OnSubstitute

func (NoOpDebugSink) OnSubstitute(Type, Type)

func (NoOpDebugSink) OnUnify

func (NoOpDebugSink) OnUnify(Type, Type, Type, uint64)

type OriginKind

type OriginKind int

OriginKind classifies the source of a type.

const (
	// OriginUnknown means provenance tracking is not enabled
	OriginUnknown OriginKind = iota
	// OriginAnnotation means the type came from an explicit type annotation
	OriginAnnotation
	// OriginLiteral means the type was inferred from a literal (3.14 → float)
	OriginLiteral
	// OriginInferred means the type was inferred through unification
	OriginInferred
	// OriginDefaulted means the type was defaulted (Num → Int/Float)
	OriginDefaulted
	// OriginFromUse means the type was inferred from a call site
	OriginFromUse
	// OriginFromPattern means the type was inferred from pattern matching
	OriginFromPattern
)

func (OriginKind) String

func (k OriginKind) String() string

String returns a human-readable name for the origin kind.

type Qualified

type Qualified struct {
	Constraints []Constraint
	Type        Type
}

Qualified represents a qualified type (type with constraints)

func (*Qualified) String

func (q *Qualified) String() string

type QualifiedScheme

type QualifiedScheme struct {
	Constraints []ClassConstraint // Non-ground class constraints
	Scheme      *Scheme           // The polymorphic type scheme
}

QualifiedScheme represents a type scheme with explicit class constraints This is used during generalization to preserve non-ground constraints e.g., ∀α. Num α ⇒ α → α → α

func NewQualifiedScheme

func NewQualifiedScheme(constraints []ClassConstraint, typeVars []string, typ Type) *QualifiedScheme

NewQualifiedScheme creates a qualified scheme from constraints and type

func (*QualifiedScheme) String

func (qs *QualifiedScheme) String() string

String returns a string representation of the qualified scheme

type ResolvedConstraint

type ResolvedConstraint struct {
	NodeID    uint64 // Core node ID where constraint was resolved
	ClassName string // "Num", "Eq", "Ord", etc.
	Type      Type   // Normalized ground type (Int, Float, etc.)
	Method    string // Method name for operators: "add", "eq", "lt", etc.
}

ResolvedConstraint records a resolved class constraint at a specific node This is used by the elaborator to insert dictionary passing

type Result

type Result struct {
	Type   Type
	Errors []error
}

Result type for type checking

type Row

type Row struct {
	Kind       Kind            // KRow(KEffect) or KRow(KRecord)
	Labels     map[string]Type // For records: field->type, For effects: effect->unit
	Tail       *RowVar         // Optional row variable for extension
	Budgets    map[string]*int // For effects: optional budget limits (nil = unlimited)
	MinBudgets map[string]*int // For effects: optional minimum usage requirements (M-DX25 M4)
}

Row represents a row type (for both records and effects)

func CanonicalizeRow

func CanonicalizeRow(r *Row) *Row

CanonicalizeRow returns the canonical representation of a row

func ElaborateEffectRow

func ElaborateEffectRow(effectNames []string) (*Row, error)

ElaborateEffectRow converts AST effect names to a normalized effect row Returns nil for empty effect sets (purity sentinel) Labels are sorted alphabetically for determinism Supports effect row variables (lowercase identifiers like 'e') for polymorphism

func ElaborateEffectRowWithBudgets

func ElaborateEffectRowWithBudgets(effects []ast.EffectAnnotation) (*Row, error)

ElaborateEffectRowWithBudgets converts AST effect annotations (with optional budgets) to a normalized effect row. Returns nil for empty effect sets (purity sentinel). Labels are sorted alphabetically for determinism. Supports @limit=N (max) and @min=N (minimum) annotations (M-DX25 M4). Supports effect row variables (lowercase identifiers like 'e') for polymorphism.

func EmptyEffectRow

func EmptyEffectRow() *Row

EmptyEffectRow creates an empty effect row

func EmptyRecordRow

func EmptyRecordRow() *Row

EmptyRecordRow creates an empty record row

func UnionEffectRows

func UnionEffectRows(a, b *Row) *Row

UnionEffectRows creates the union of two effect rows nil is treated as the identity (pure) Result is always sorted for determinism For budgets: when both rows have a budget for the same effect, budgets are summed (nested scopes compose by addition for total allowed invocations)

func UnionEffects

func UnionEffects(rows ...*Row) *Row

UnionEffects computes the union of multiple effect rows

func (*Row) Equals

func (r *Row) Equals(other Type) bool

func (*Row) GetKind

func (r *Row) GetKind() Kind

func (*Row) MarshalJSON

func (r *Row) MarshalJSON() ([]byte, error)

func (*Row) String

func (r *Row) String() string

func (*Row) Substitute

func (r *Row) Substitute(subs map[string]Type) Type

type RowEq

type RowEq struct {
	Left  *Row
	Right *Row
	Path  []string
}

RowEq represents a row equality constraint

func (RowEq) String

func (c RowEq) String() string

type RowUnifier

type RowUnifier struct {
	// contains filtered or unexported fields
}

RowUnifier handles row unification with principal types

func NewRowUnifier

func NewRowUnifier() *RowUnifier

NewRowUnifier creates a new row unifier

func (*RowUnifier) SetParentUnifier

func (ru *RowUnifier) SetParentUnifier(u *Unifier)

SetParentUnifier sets the parent unifier (M-FIX-NESTED-RECORD-LIST) This is needed for alias expansion when unifying field types in rows

func (*RowUnifier) UnifyRows

func (ru *RowUnifier) UnifyRows(r1, r2 *Row, sub Substitution) (Substitution, error)

UnifyRows unifies two rows, returning an updated substitution or error

type RowVar

type RowVar struct {
	Name string
	Kind Kind // Should be KRow(KEffect) or KRow(KRecord)
}

RowVar represents a row variable with kind

func (*RowVar) Equals

func (r *RowVar) Equals(other Type) bool

func (*RowVar) GetKind

func (r *RowVar) GetKind() Kind

func (*RowVar) MarshalJSON

func (t *RowVar) MarshalJSON() ([]byte, error)

func (*RowVar) String

func (r *RowVar) String() string

func (*RowVar) Substitute

func (r *RowVar) Substitute(subs map[string]Type) Type

type Scheme

type Scheme struct {
	TypeVars    []string     // Quantified type variables
	RowVars     []string     // Quantified row variables
	Constraints []Constraint // Type class constraints
	Type        Type
}

Scheme represents a type scheme with quantified variables

func UnmarshalScheme

func UnmarshalScheme(data []byte) (*Scheme, error)

UnmarshalScheme deserializes a Scheme from JSON.

func (*Scheme) Instantiate

func (s *Scheme) Instantiate(fresh func(Kind) Type) Type

Instantiate creates a fresh instance of the type scheme

func (*Scheme) String

func (s *Scheme) String() string

type SimpleEffect

type SimpleEffect struct {
	Name string
}

SimpleEffect represents a basic effect (IO, FS, Net, etc.)

func (*SimpleEffect) Equals

func (e *SimpleEffect) Equals(other EffectType) bool

func (*SimpleEffect) String

func (e *SimpleEffect) String() string

type SourceSpan

type SourceSpan struct {
	File   string // Source file path
	Line   int    // Line number (1-based)
	Column int    // Column number (1-based)
}

SourceSpan represents a source code location for provenance tracking. Defined here to avoid circular dependencies with ast package.

func (SourceSpan) String

func (s SourceSpan) String() string

String returns a human-readable location string.

type Substitution

type Substitution map[string]Type

Substitution maps variable names to types

func ComposeSubstitutions

func ComposeSubstitutions(s1, s2 Substitution) Substitution

ComposeSubstitutions composes two substitutions

type TApp

type TApp struct {
	Constructor Type
	Args        []Type
}

TApp represents type application (e.g., Maybe[int])

func (*TApp) Equals

func (t *TApp) Equals(other Type) bool

func (*TApp) MarshalJSON

func (t *TApp) MarshalJSON() ([]byte, error)

func (*TApp) String

func (t *TApp) String() string

func (*TApp) Substitute

func (t *TApp) Substitute(subs map[string]Type) Type

type TArray

type TArray struct {
	Element Type
}

TArray represents an array type with O(1) indexed access

func (*TArray) Equals

func (t *TArray) Equals(other Type) bool

func (*TArray) MarshalJSON

func (t *TArray) MarshalJSON() ([]byte, error)

func (*TArray) String

func (t *TArray) String() string

func (*TArray) Substitute

func (t *TArray) Substitute(subs map[string]Type) Type

type TCon

type TCon struct {
	Name string
}

TCon represents a type constructor (int, bool, string, etc.)

func (*TCon) Equals

func (t *TCon) Equals(other Type) bool

func (*TCon) MarshalJSON

func (t *TCon) MarshalJSON() ([]byte, error)

func (*TCon) String

func (t *TCon) String() string

func (*TCon) Substitute

func (t *TCon) Substitute(subs map[string]Type) Type

type TFunc2

type TFunc2 struct {
	Params    []Type
	EffectRow *Row // Row of kind KRow(KEffect)
	Return    Type
}

TFunc2 represents a function type with effect row

func (*TFunc2) Equals

func (t *TFunc2) Equals(other Type) bool

func (*TFunc2) GetKind

func (t *TFunc2) GetKind() Kind

func (*TFunc2) MarshalJSON

func (t *TFunc2) MarshalJSON() ([]byte, error)

func (*TFunc2) String

func (t *TFunc2) String() string

func (*TFunc2) Substitute

func (t *TFunc2) Substitute(subs map[string]Type) Type

type TList deprecated

type TList struct {
	Element Type
}

TList represents a list type.

Deprecated: Use TApp("list", T) instead. The [T] syntax in source code normalizes to TApp("list", T) during parsing (DX-17 Phase 2). TList will be removed in v0.7.0. Use the AsList helper to check if a type is a list without depending on the internal representation.

func (*TList) Equals

func (t *TList) Equals(other Type) bool

func (*TList) MarshalJSON

func (t *TList) MarshalJSON() ([]byte, error)

func (*TList) String

func (t *TList) String() string

func (*TList) Substitute

func (t *TList) Substitute(subs map[string]Type) Type

type TMap

type TMap struct {
	Key   Type
	Value Type
}

TMap represents a map type Map[K, V] with O(1) lookup

func (*TMap) Equals

func (t *TMap) Equals(other Type) bool

func (*TMap) MarshalJSON

func (t *TMap) MarshalJSON() ([]byte, error)

func (*TMap) String

func (t *TMap) String() string

func (*TMap) Substitute

func (t *TMap) Substitute(subs map[string]Type) Type

type TRecord

type TRecord struct {
	Fields   map[string]Type
	Row      Type   // Row variable for extensibility
	TypeName string // M-CROSS-MODULE: Nominal type name (e.g., "ArrivalState") when unified with TCon
}

TRecord represents a record type with row polymorphism

func TRecord2ToTRecord

func TRecord2ToTRecord(new *TRecord2) *TRecord

TRecord2ToTRecord converts new TRecord2 to old TRecord (for compatibility)

func (*TRecord) Equals

func (t *TRecord) Equals(other Type) bool

func (*TRecord) MarshalJSON

func (t *TRecord) MarshalJSON() ([]byte, error)

func (*TRecord) String

func (t *TRecord) String() string

func (*TRecord) Substitute

func (t *TRecord) Substitute(subs map[string]Type) Type

type TRecord2

type TRecord2 struct {
	Row *Row // Row of kind KRow(KRecord)
}

TRecord2 represents a record type with row

func TRecordToTRecord2

func TRecordToTRecord2(old *TRecord) *TRecord2

TRecordToTRecord2 converts old TRecord to new TRecord2

func (*TRecord2) Equals

func (t *TRecord2) Equals(other Type) bool

func (*TRecord2) GetKind

func (t *TRecord2) GetKind() Kind

func (*TRecord2) MarshalJSON

func (t *TRecord2) MarshalJSON() ([]byte, error)

func (*TRecord2) String

func (t *TRecord2) String() string

func (*TRecord2) Substitute

func (t *TRecord2) Substitute(subs map[string]Type) Type

type TRecordOpen

type TRecordOpen struct {
	Fields map[string]Type // Known fields (subset)
	Row    Type            // Row variable for unknown fields
}

TRecordOpen marks an open record for subsumption (field access) Example: {x: α | ρ} where we only know field 'x' exists This is a compatibility shim for M-R5; will be replaced by TRecord2 in Day 2

func (*TRecordOpen) Equals

func (t *TRecordOpen) Equals(other Type) bool

func (*TRecordOpen) MarshalJSON

func (t *TRecordOpen) MarshalJSON() ([]byte, error)

func (*TRecordOpen) String

func (t *TRecordOpen) String() string

func (*TRecordOpen) Substitute

func (t *TRecordOpen) Substitute(subs map[string]Type) Type

type TTuple

type TTuple struct {
	Elements []Type
}

TTuple represents a tuple type

func (*TTuple) Equals

func (t *TTuple) Equals(other Type) bool

func (*TTuple) MarshalJSON

func (t *TTuple) MarshalJSON() ([]byte, error)

func (*TTuple) String

func (t *TTuple) String() string

func (*TTuple) Substitute

func (t *TTuple) Substitute(subs map[string]Type) Type

type TVar

type TVar struct {
	Name string
}

TVar represents a type variable

func (*TVar) Equals

func (t *TVar) Equals(other Type) bool

func (*TVar) MarshalJSON

func (t *TVar) MarshalJSON() ([]byte, error)

func (*TVar) String

func (t *TVar) String() string

func (*TVar) Substitute

func (t *TVar) Substitute(subs map[string]Type) Type

type TVar2

type TVar2 struct {
	Name string
	Kind Kind
}

TVar2 represents a type variable with kind

func (*TVar2) Equals

func (t *TVar2) Equals(other Type) bool

func (*TVar2) GetKind

func (t *TVar2) GetKind() Kind

func (*TVar2) MarshalJSON

func (t *TVar2) MarshalJSON() ([]byte, error)

func (*TVar2) String

func (t *TVar2) String() string

func (*TVar2) Substitute

func (t *TVar2) Substitute(subs map[string]Type) Type

type Type

type Type interface {
	String() string
	Equals(Type) bool
	Substitute(map[string]Type) Type
}

Type represents a type in the AILANG type system

func ApplySubstitution

func ApplySubstitution(sub Substitution, t Type) Type

ApplySubstitution applies a substitution to a type with cycle detection

func AsList

func AsList(t Type) (elem Type, ok bool)

AsList checks if a type is a list type (either TList or TApp("list", ...)). Returns the element type and true if it's a list, nil and false otherwise.

This helper addresses DX-17: TList/TApp unification bug. The parser creates TList for [T] syntax, while the type builder creates TApp("list", T) for builtins. This helper recognizes both representations.

Example:

if elem, ok := types.AsList(paramType); ok {
    // paramType is a list with element type elem
}

Note: Case-sensitive - only matches lowercase "list" (not "List").

func NewTypeVar

func NewTypeVar() Type

NewTypeVar creates a fresh type variable

func RecordFieldType

func RecordFieldType(rec Type, field string) (Type, bool)

RecordFieldType gets the type of a field in a record

func RecordSelection

func RecordSelection(record *Row, field string) (Type, error)

RecordSelection checks if a record type has a field and returns its type

func Unit

func Unit() Type

Unit returns the Unit type

func UnmarshalType

func UnmarshalType(data []byte) (Type, error)

UnmarshalType deserializes a types.Type from JSON.

type TypeCheckError

type TypeCheckError struct {
	Kind       TypeErrorKind
	Path       []string // Field/expression path
	Position   string   // Source position
	Expected   Type
	Actual     Type
	Message    string
	Suggestion string
}

TypeCheckError represents a detailed type checking error

func NewArityMismatchError

func NewArityMismatchError(expected, actual int, path []string) *TypeCheckError

NewArityMismatchError creates an arity mismatch error

func NewDuplicateFieldError

func NewDuplicateFieldError(field string, pos1, pos2 string) *TypeCheckError

NewDuplicateFieldError creates a TC_REC_002 error

func NewFieldTypeMismatchError

func NewFieldTypeMismatchError(field string, expected, actual Type, position string) *TypeCheckError

NewFieldTypeMismatchError creates a TC_REC_004 error

func NewKindMismatchError

func NewKindMismatchError(expected, actual Kind, path []string) *TypeCheckError

NewKindMismatchError creates a kind mismatch error

func NewMissingFieldError

func NewMissingFieldError(field string, recordType Type, position string) *TypeCheckError

NewMissingFieldError creates a TC_REC_001 error

func NewOccursCheckError

func NewOccursCheckError(varName string, inType Type) *TypeCheckError

NewOccursCheckError creates an occurs check error

func NewRowMismatchError

func NewRowMismatchError(expected, actual *Row, path []string) *TypeCheckError

NewRowMismatchError creates a detailed row mismatch error

func NewRowOccursError

func NewRowOccursError(rowVar string, inType Type, position string) *TypeCheckError

NewRowOccursError creates a TC_REC_003 error

func NewTypeMismatchError

func NewTypeMismatchError(expected, actual Type, path []string) *TypeCheckError

NewTypeMismatchError creates a type mismatch error

func NewUnboundVariableError

func NewUnboundVariableError(name string, path []string) *TypeCheckError

NewUnboundVariableError creates an unbound variable error

func NewUnsolvedConstraintError

func NewUnsolvedConstraintError(className string, typ Type, path []string) *TypeCheckError

NewUnsolvedConstraintError creates an unsolved type class constraint error

func (*TypeCheckError) Error

func (e *TypeCheckError) Error() string

type TypeChecker

type TypeChecker struct {
	// contains filtered or unexported fields
}

TypeChecker is the main type checking interface

func NewTypeChecker

func NewTypeChecker() *TypeChecker

NewTypeChecker creates a new type checker

func (*TypeChecker) CheckProgram

func (tc *TypeChecker) CheckProgram(program *ast.Program) (*TypedProgram, error)

CheckProgram type checks an entire program

type TypeClass

type TypeClass struct {
	Name       string
	TypeParam  string
	Superclass string // Optional superclass
	Methods    map[string]*TypeScheme
}

TypeClass represents a type class

type TypeConstraint

type TypeConstraint interface {
	String() string
	// contains filtered or unexported methods
}

TypeConstraint represents a constraint to be solved

type TypeDebugSink

type TypeDebugSink interface {
	// OnFreshTypeVar is called when a fresh type variable is created.
	// The tv parameter is the type variable (typically *TVar2).
	OnFreshTypeVar(tv Type, nodeID uint64, origin OriginKind)

	// OnUnify is called when two types are unified.
	OnUnify(left, right Type, result Type, nodeID uint64)

	// OnSubstitute is called when a type variable is substituted.
	// The tv parameter is the type variable being substituted.
	OnSubstitute(tv Type, resolved Type)

	// OnDefault is called when a type variable is defaulted.
	// The tv parameter is the type variable being defaulted.
	OnDefault(tv Type, defaulted Type, reason string)

	// OnConstraintAdd is called when a constraint is added.
	OnConstraintAdd(className string, ty Type, nodeID uint64)

	// OnConstraintResolve is called when a constraint is resolved.
	OnConstraintResolve(className string, ty Type, method string, nodeID uint64)
}

TypeDebugSink receives events during type inference for debugging. Implementations should be designed for zero overhead when not actively collecting events (NoOpDebugSink) or collecting structured events for later formatting (VerboseDebugSink).

type TypeEnv

type TypeEnv struct {
	// contains filtered or unexported fields
}

TypeEnv represents a type environment mapping names to types or schemes

func NewTypeEnv

func NewTypeEnv() *TypeEnv

NewTypeEnv creates a new empty type environment

func NewTypeEnvWithBuiltins

func NewTypeEnvWithBuiltins() *TypeEnv

NewTypeEnvWithBuiltins creates a type environment with builtin functions.

This delegates to internal/link/env_seed.go which seeds the environment from the linker's $builtin interface, ensuring all 49 spec-registered builtins (with correct effect rows) are visible to the typechecker.

func (*TypeEnv) BindScheme

func (env *TypeEnv) BindScheme(name string, scheme *Scheme)

BindScheme adds a scheme binding to the environment (for REPL persistence) This mutates the environment in-place, unlike Extend which creates a child. Use this only when you need top-level bindings to persist (e.g., REPL).

func (*TypeEnv) BindType

func (env *TypeEnv) BindType(name string, typ Type)

BindType adds a type binding to the environment (for REPL persistence) This mutates the environment in-place, unlike Extend which creates a child. Use this only when you need top-level bindings to persist (e.g., REPL).

func (*TypeEnv) Extend

func (env *TypeEnv) Extend(name string, typ Type) *TypeEnv

Extend creates a new environment with an additional binding

func (*TypeEnv) ExtendScheme

func (env *TypeEnv) ExtendScheme(name string, scheme *Scheme) *TypeEnv

ExtendScheme creates a new environment with a scheme binding

func (*TypeEnv) FreeRowVars

func (env *TypeEnv) FreeRowVars() map[string]bool

FreeRowVars returns all free row variables in the environment

func (*TypeEnv) FreeTypeVars

func (env *TypeEnv) FreeTypeVars() map[string]bool

FreeTypeVars returns all free type variables in the environment

func (*TypeEnv) Lookup

func (env *TypeEnv) Lookup(name string) (interface{}, error)

Lookup finds a type or scheme in the environment

type TypeEq

type TypeEq struct {
	Left  Type
	Right Type
	Path  []string // Source location path
}

TypeEq represents a type equality constraint

func (TypeEq) String

func (c TypeEq) String() string

type TypeError

type TypeError struct {
	Message string
	Pos     string
}

Error types

func (*TypeError) Error

func (e *TypeError) Error() string

type TypeErrorKind

type TypeErrorKind string

TypeErrorKind represents the kind of type error

const (
	KindMismatchError       TypeErrorKind = "kind_mismatch"
	TypeMismatchError       TypeErrorKind = "type_mismatch"
	RowMismatchError        TypeErrorKind = "row_mismatch"
	OccursCheckError        TypeErrorKind = "occurs_check"
	UnboundVariableError    TypeErrorKind = "unbound_variable"
	ArityMismatchError      TypeErrorKind = "arity_mismatch"
	MissingFieldError       TypeErrorKind = "missing_field"
	ExtraFieldError         TypeErrorKind = "extra_field"
	MissingEffectError      TypeErrorKind = "missing_effect"
	ExtraEffectError        TypeErrorKind = "extra_effect"
	UnsolvedConstraintError TypeErrorKind = "unsolved_constraint"
)

type TypeHead

type TypeHead int

TypeHead represents the head constructor of a type for operator lowering

const (
	HeadUnknown TypeHead = iota
	HeadInt
	HeadFloat
	HeadString
	HeadBool
	HeadList
	HeadArray
	HeadMap
	HeadRecord
	HeadFunc
	HeadUnit
	HeadBytes
)
func Head(t Type) TypeHead

Head returns the head constructor of a type for type-guided operator lowering. This is used to determine which builtin variant to use (e.g., _str_concat vs _list_concat).

Examples:

  • Head(TInt) → HeadInt
  • Head(TString) → HeadString
  • Head(TApp{Constructor: TCon{Name: "list"}, ...}) → HeadList
  • Head(TVar{...}) → HeadUnknown (type variable, need more inference)

func (TypeHead) String

func (th TypeHead) String() string

String returns a human-readable name for the type head

type TypeInfo

type TypeInfo map[ast.Expr]Type

TypeInfo maps AST expression nodes to their inferred types (principal types after generalization) This uses pointer identity as the key, which is stable across compilation passes

func NewTypeInfo

func NewTypeInfo() TypeInfo

NewTypeInfo creates a new TypeInfo map

func (TypeInfo) Get

func (ti TypeInfo) Get(expr ast.Expr) (Type, bool)

Get returns the type for the given expression and a boolean indicating if it was found

func (TypeInfo) Has

func (ti TypeInfo) Has(expr ast.Expr) bool

Has checks if a type exists for the given expression

func (TypeInfo) Must

func (ti TypeInfo) Must(expr ast.Expr) Type

Must returns the type for the given expression, or panics with a helpful error if not found

func (TypeInfo) Set

func (ti TypeInfo) Set(expr ast.Expr, t Type)

Set stores a type for the given expression

type TypeOrigin

type TypeOrigin struct {
	Kind   OriginKind // How this type was determined
	NodeID uint64     // Originating node
	Span   SourceSpan // Source location
	Note   string     // Human-readable description
}

TypeOrigin tracks where a type came from for provenance debugging. Used by VerboseDebugSink to answer "why does this have type X?" questions.

type TypeReport

type TypeReport struct {
	NodeID      uint64          // The Core node ID
	Raw         Type            // What's in CoreTI (may have TVars)
	Resolved    Type            // After applying full substitution
	Constraints []ConstraintRef // Constraints mentioning this type's variables
	Origins     []TypeOrigin    // M-DX11: Provenance chain (where type came from)
	Found       bool            // Whether the node was found in CoreTI
}

TypeReport consolidates type information for a Core node. It is a thin façade over existing structures, always derived from live data.

func (TypeReport) FormatDetailed

func (r TypeReport) FormatDetailed() string

FormatDetailed returns a multi-line detailed representation of the report. This format matches the design doc output format for --debug-types.

func (TypeReport) String

func (r TypeReport) String() string

String returns a human-readable representation of the report.

type TypeScheme

type TypeScheme struct {
	TypeVars   []string
	EffectVars []string
	Type       Type
}

TypeScheme represents a polymorphic type scheme

func (*TypeScheme) Instantiate

func (t *TypeScheme) Instantiate() Type

Instantiate creates a fresh instance of the type scheme

func (*TypeScheme) String

func (t *TypeScheme) String() string

type TypeV2

type TypeV2 interface {
	Type
	GetKind() Kind
}

TypeV2 represents types with proper kind tracking

type TypedExpression

type TypedExpression struct {
	Expr    interface{} // ast.Expression
	Type    Type
	Effects *Row
}

TypedExpression wraps an expression with its type

type TypedExpressionStatement

type TypedExpressionStatement struct {
	Expression *TypedExpression
}

TypedExpressionStatement is a typed expression statement

func (*TypedExpressionStatement) GetType

func (s *TypedExpressionStatement) GetType() Type

type TypedFunctionDeclaration

type TypedFunctionDeclaration struct {
	Name       interface{}   // Can be ast.Expression or nil
	Params     []interface{} // ast.Expression items
	ParamTypes []Type
	Body       interface{} // ast.Expression
	BodyType   Type
	Effects    *Row
}

TypedFunctionDeclaration is a typed function declaration

func (*TypedFunctionDeclaration) GetType

func (f *TypedFunctionDeclaration) GetType() Type

type TypedProgram

type TypedProgram struct {
	Statements []TypedStatement
}

TypedProgram represents a type-checked program

type TypedStatement

type TypedStatement interface {
	GetType() Type
	// contains filtered or unexported methods
}

TypedStatement represents a type-checked statement

type UnificationError

type UnificationError struct {
	Type1 Type
	Type2 Type
	Pos   string
}

UnificationError represents a unification failure

func (*UnificationError) Error

func (e *UnificationError) Error() string

type Unifier

type Unifier struct {
	// contains filtered or unexported fields
}

Unifier handles type unification with occurs check

func NewUnifier

func NewUnifier() *Unifier

NewUnifier creates a new unifier

func NewUnifierWithAliases

func NewUnifierWithAliases(aliases map[string]Type) *Unifier

NewUnifierWithAliases creates a unifier with type alias expansion support M-BUGFIX: This allows ADT variants with alias parameters to work correctly

func (*Unifier) SetDebugSink

func (u *Unifier) SetDebugSink(sink TypeDebugSink)

SetDebugSink sets the debug sink for OnSubstitute events during unification. M-DX11-PHASE2: Called by InferenceContext/CoreTypeChecker to wire debugging.

func (*Unifier) Unify

func (u *Unifier) Unify(t1, t2 Type, sub Substitution) (Substitution, error)

Unify attempts to unify two types, returning an updated substitution

type VerboseDebugSink

type VerboseDebugSink struct {
	// contains filtered or unexported fields
}

VerboseDebugSink collects debug events and type provenance for debugging. Events are stored in order and can be retrieved via Events(). Provenance tracks where each type variable's type came from.

func NewVerboseDebugSink

func NewVerboseDebugSink() *VerboseDebugSink

NewVerboseDebugSink creates a new verbose debug sink.

func (*VerboseDebugSink) AllProvenance

func (s *VerboseDebugSink) AllProvenance() map[string][]TypeOrigin

AllProvenance returns the complete provenance map. Useful for iterating over all tracked type variables.

func (*VerboseDebugSink) Clear

func (s *VerboseDebugSink) Clear()

Clear removes all collected events and provenance.

func (*VerboseDebugSink) Events

func (s *VerboseDebugSink) Events() []DebugEvent

Events returns all collected debug events.

func (*VerboseDebugSink) GetProvenance

func (s *VerboseDebugSink) GetProvenance(typeVarName string) []TypeOrigin

GetProvenance returns all recorded origins for a type variable. Returns nil if no provenance has been recorded.

func (*VerboseDebugSink) OnConstraintAdd

func (s *VerboseDebugSink) OnConstraintAdd(className string, ty Type, nodeID uint64)

func (*VerboseDebugSink) OnConstraintResolve

func (s *VerboseDebugSink) OnConstraintResolve(className string, ty Type, method string, nodeID uint64)

func (*VerboseDebugSink) OnDefault

func (s *VerboseDebugSink) OnDefault(tv Type, defaulted Type, reason string)

func (*VerboseDebugSink) OnFreshTypeVar

func (s *VerboseDebugSink) OnFreshTypeVar(tv Type, nodeID uint64, origin OriginKind)

func (*VerboseDebugSink) OnSubstitute

func (s *VerboseDebugSink) OnSubstitute(tv Type, resolved Type)

func (*VerboseDebugSink) OnUnify

func (s *VerboseDebugSink) OnUnify(left, right Type, result Type, nodeID uint64)

func (*VerboseDebugSink) RecordProvenance

func (s *VerboseDebugSink) RecordProvenance(typeVarName string, origin TypeOrigin)

RecordProvenance adds a type origin for a type variable. Multiple origins can be recorded for the same type variable (e.g., inferred, then defaulted).

Directories

Path Synopsis
Package traverse provides safe type traversal with automatic cycle detection.
Package traverse provides safe type traversal with automatic cycle detection.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL