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:
- Let-bound variables: The substitution tracks Let bindings but doesn't always resolve Var references to their binding's concrete type
- 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
- Variables
- func CanonKey(namespace, className string, typ Type, method string) string
- func EffectRowDifference(a, b *Row) []string
- func EvalNot(L Label, ell Label) bool
- func ExtractTVarName(t Type) (string, bool)
- func FormatDefaultingTraces(traces []DefaultingTrace) string
- func FormatEffectRow(row *Row) string
- func IsGroundType(t Type) bool
- func IsKnownEffect(name string) bool
- func IsOpenRecord(rec Type) bool
- func IsTVar(t Type) bool
- func LabelEqual(a, b Label) bool
- func LabelSubsumes(L, ell Label) bool
- func MakeDictionaryKey(namespace, className string, typ Type, method string) string
- func MarshalCoreTypeInfo(cti CoreTypeInfo) ([]byte, error)
- func MarshalKind(k Kind) ([]byte, error)
- func MarshalLabel(l Label) ([]byte, error)
- func MarshalScheme(s *Scheme) ([]byte, error)
- func NormalizeTypeName(t Type) string
- func OperatorMethod(op string, isUnary bool) string
- func ParseDictionaryKey(key string) (namespace, className, typeNF, method string, err error)
- func RecordHasField(rec Type, field string) bool
- func SafeEquals(t1, t2 Type) bool
- func SafeTypeString(t Type) string
- func SetBuiltinEnvFactory(factory func() *TypeEnv)
- func SubsumeEffectRows(a, b *Row) bool
- func TruncatedTypeString(t Type, maxLen int) string
- func TypeCheckFile(filename string, program *ast.Program) error
- type Builder
- func (b *Builder) App(con string, args ...Type) Type
- func (b *Builder) Bool() Type
- func (b *Builder) Bytes() Type
- func (b *Builder) Con(name string) Type
- func (b *Builder) Float() Type
- func (b *Builder) Func(params ...Type) *FuncBuilder
- func (b *Builder) Int() Type
- func (b *Builder) List(elem Type) Type
- func (b *Builder) Map(key, val Type) Type
- func (b *Builder) Rec(pairs ...interface{}) Type
- func (b *Builder) Record(fields ...FieldSpec) Type
- func (b *Builder) String() Type
- func (b *Builder) Unit() Type
- func (b *Builder) Var(name string) Type
- type ClassConstraint
- type ClassInstance
- type Constraint
- type ConstraintRef
- type CoreTypeChecker
- func (tc *CoreTypeChecker) ApplySubstEverywhere(sub Substitution, monotype Type, constraints []ClassConstraint, ...) (Type, []ClassConstraint, typedast.TypedNode, interface{})
- func (tc *CoreTypeChecker) CheckCoreExpr(expr core.CoreExpr, env *TypeEnv) (typedast.TypedNode, *TypeEnv, error)
- func (tc *CoreTypeChecker) CheckCoreProgram(prog *core.Program) (*typedast.TypedProgram, error)
- func (tc *CoreTypeChecker) DumpInstantiations() map[string]interface{}
- func (tc *CoreTypeChecker) EnableInstantiationTracking()
- func (tc *CoreTypeChecker) EnableTraceDefaulting(enable bool)
- func (tc *CoreTypeChecker) FillOperatorMethods(expr core.CoreExpr)
- func (tc *CoreTypeChecker) FinalizeSubstitutions()
- func (tc *CoreTypeChecker) GetAliasEnv() map[string]Type
- func (tc *CoreTypeChecker) GetResolvedConstraints() map[uint64]*ResolvedConstraint
- func (tc *CoreTypeChecker) InferWithConstraints(expr core.CoreExpr, env *TypeEnv) (typedast.TypedNode, *TypeEnv, Type, []Constraint, error)
- func (tc *CoreTypeChecker) RegisterADTTypeParams(typeName string, paramCount int)
- func (tc *CoreTypeChecker) RegisterConstructorType(ctorName, typeName string)
- func (tc *CoreTypeChecker) RegisterTypeAlias(name string, target Type)
- func (tc *CoreTypeChecker) SetADTTypeParams(params map[string]int)
- func (tc *CoreTypeChecker) SetConstructorTypes(ctors map[string]string)
- func (tc *CoreTypeChecker) SetDebugMode(debug bool)
- func (tc *CoreTypeChecker) SetDebugSink(sink TypeDebugSink)
- func (tc *CoreTypeChecker) SetDefaultingConfig(config *DefaultingConfig)
- func (tc *CoreTypeChecker) SetEffectAnnotations(annots map[uint64][]string)
- func (tc *CoreTypeChecker) SetEffectAnnotationsFull(annots map[uint64][]ast.EffectAnnotation)
- func (tc *CoreTypeChecker) SetGlobalType(key string, scheme *Scheme)
- func (tc *CoreTypeChecker) SetGlobalTypes(types map[string]*Scheme)
- func (tc *CoreTypeChecker) SetParamTypeAnnotations(annots map[uint64][]Type)
- func (tc *CoreTypeChecker) SetReturnTypeAnnotations(annots map[uint64]Type)
- func (tc *CoreTypeChecker) TypeReport(nodeID uint64) TypeReport
- type CoreTypeInfo
- func (cti CoreTypeInfo) ApplySubstitution(sub Substitution)
- func (cti CoreTypeInfo) Get(nodeID uint64) (Type, bool)
- func (cti CoreTypeInfo) GetForExpr(expr core.CoreExpr) (Type, bool)
- func (cti CoreTypeInfo) Has(nodeID uint64) bool
- func (cti CoreTypeInfo) Must(nodeID uint64) Type
- func (cti CoreTypeInfo) MustForExpr(expr core.CoreExpr) Type
- func (cti CoreTypeInfo) Set(nodeID uint64, t Type)
- type CycleInfo
- type CycleKind
- type DebugEvent
- type DebugEventKind
- type DeclassError
- type DefaultingConfig
- type DefaultingTrace
- type DerivedADTEquality
- type Dict
- type DictParam
- type DictionaryEntry
- type DictionaryRegistry
- func (r *DictionaryRegistry) Lookup(key string) (DictionaryEntry, bool)
- func (r *DictionaryRegistry) LookupMethod(namespace, className string, typ Type, method string) (interface{}, bool)
- func (r *DictionaryRegistry) Register(namespace, className, typeName, method string, impl interface{})
- func (r *DictionaryRegistry) RegisterDerivedEq(typeName string)
- func (r *DictionaryRegistry) RegisterInstance(key string, dict interface{})
- func (r *DictionaryRegistry) ValidateRegistry() error
- type EffectRowOld
- type EffectType
- type EffectVar
- type ErrorList
- type FieldSpec
- type FuncBuilder
- type InferenceContext
- type Instance
- type InstanceEnv
- func (env *InstanceEnv) Add(inst *ClassInstance) error
- func (env *InstanceEnv) AddDerivedEqForADT(typeName string) error
- func (env *InstanceEnv) DefaultFor(class string) Type
- func (env *InstanceEnv) GetDefault(class string) Type
- func (env *InstanceEnv) Lookup(class string, typ Type) (*ClassInstance, error)
- func (env *InstanceEnv) SetDefault(class string, typ Type)
- type Instantiation
- type KEffect
- type KRecord
- type KRow
- type KStar
- type Kind
- type Label
- func JoinLabelList(types []Type) Label
- func JoinLabels(a, b Type) Label
- func LabelBottom() Label
- func LabelConst(name string) Label
- func LabelJoin(a, b Label) Label
- func LabelOf(t Type) Label
- func LabelVar(name string) Label
- func PurePropagateLabel(returnLabel Label, argTypes []Type) Label
- func UnmarshalLabel(data []byte) (Label, error)
- type MissingInstanceError
- type ModuleScopedDefaults
- type NoOpDebugSink
- func (NoOpDebugSink) OnConstraintAdd(string, Type, uint64)
- func (NoOpDebugSink) OnConstraintResolve(string, Type, string, uint64)
- func (NoOpDebugSink) OnDefault(Type, Type, string)
- func (NoOpDebugSink) OnFreshTypeVar(Type, uint64, OriginKind)
- func (NoOpDebugSink) OnSubstitute(Type, Type)
- func (NoOpDebugSink) OnUnify(Type, Type, Type, uint64)
- type OriginKind
- type Qualified
- type QualifiedScheme
- type ResolvedConstraint
- type Result
- type Row
- func CanonicalizeRow(r *Row) *Row
- func ElaborateEffectRow(effectNames []string) (*Row, error)
- func ElaborateEffectRowWithBudgets(effects []ast.EffectAnnotation) (*Row, error)
- func EmptyEffectRow() *Row
- func EmptyRecordRow() *Row
- func UnionEffectRows(a, b *Row) *Row
- func UnionEffects(rows ...*Row) *Row
- type RowEq
- type RowUnifier
- type RowVar
- type Scheme
- type SimpleEffect
- type SinkError
- type SourceSpan
- type Substitution
- type TApp
- type TArray
- type TCon
- type TFunc2
- type TLabelled
- type TListdeprecated
- type TMap
- type TRecord
- type TRecord2
- type TRecordOpen
- type TTuple
- type TVar
- type TVar2
- type Type
- func ApplySubstitution(sub Substitution, t Type) Type
- func AsList(t Type) (elem Type, ok bool)
- func NewTypeVar() Type
- func RecordFieldType(rec Type, field string) (Type, bool)
- func RecordSelection(record *Row, field string) (Type, error)
- func StripLabel(t Type) Type
- func Unit() Type
- func UnmarshalType(data []byte) (Type, error)
- func WithLabel(t Type, l Label) Type
- type TypeCheckError
- func NewArityMismatchError(expected, actual int, path []string) *TypeCheckError
- func NewDuplicateFieldError(field string, pos1, pos2 string) *TypeCheckError
- func NewFieldTypeMismatchError(field string, expected, actual Type, position string) *TypeCheckError
- func NewKindMismatchError(expected, actual Kind, path []string) *TypeCheckError
- func NewMissingFieldError(field string, recordType Type, position string) *TypeCheckError
- func NewOccursCheckError(varName string, inType Type) *TypeCheckError
- func NewRowMismatchError(expected, actual *Row, path []string) *TypeCheckError
- func NewRowOccursError(rowVar string, inType Type, position string) *TypeCheckError
- func NewTypeMismatchError(expected, actual Type, path []string) *TypeCheckError
- func NewUnboundVariableError(name string, path []string) *TypeCheckError
- func NewUnsolvedConstraintError(className string, typ Type, path []string) *TypeCheckError
- type TypeChecker
- type TypeClass
- type TypeConstraint
- type TypeDebugSink
- type TypeEnv
- func (env *TypeEnv) BindScheme(name string, scheme *Scheme)
- func (env *TypeEnv) BindType(name string, typ Type)
- func (env *TypeEnv) Extend(name string, typ Type) *TypeEnv
- func (env *TypeEnv) ExtendScheme(name string, scheme *Scheme) *TypeEnv
- func (env *TypeEnv) FreeRowVars() map[string]bool
- func (env *TypeEnv) FreeTypeVars() map[string]bool
- func (env *TypeEnv) Lookup(name string) (interface{}, error)
- type TypeEq
- type TypeError
- type TypeErrorKind
- type TypeHead
- type TypeInfo
- type TypeOrigin
- type TypeReport
- type TypeScheme
- type TypeV2
- type TypedExpression
- type TypedExpressionStatement
- type TypedFunctionDeclaration
- type TypedProgram
- type TypedStatement
- type UnificationError
- type Unifier
- type VerboseDebugSink
- func (s *VerboseDebugSink) AllProvenance() map[string][]TypeOrigin
- func (s *VerboseDebugSink) Clear()
- func (s *VerboseDebugSink) Events() []DebugEvent
- func (s *VerboseDebugSink) GetProvenance(typeVarName string) []TypeOrigin
- func (s *VerboseDebugSink) OnConstraintAdd(className string, ty Type, nodeID uint64)
- func (s *VerboseDebugSink) OnConstraintResolve(className string, ty Type, method string, nodeID uint64)
- func (s *VerboseDebugSink) OnDefault(tv Type, defaulted Type, reason string)
- func (s *VerboseDebugSink) OnFreshTypeVar(tv Type, nodeID uint64, origin OriginKind)
- func (s *VerboseDebugSink) OnSubstitute(tv Type, resolved Type)
- func (s *VerboseDebugSink) OnUnify(left, right Type, result Type, nodeID uint64)
- func (s *VerboseDebugSink) RecordProvenance(typeVarName string, origin TypeOrigin)
Constants ¶
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)
const MaxStringifyDepth = 100
MaxStringifyDepth is the maximum depth for type stringification. Beyond this, types are truncated with "..." to prevent hangs on cyclic types.
Variables ¶
var ( Star = KStar{} Effect = KEffect{} Record = KRecord{} EffectRow = KRow{ElemKind: Effect} RecordRow = KRow{ElemKind: Record} )
Common kinds
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
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 ¶
CanonKey is an alias for MakeDictionaryKey - the single entry point for all dictionary key generation to ensure consistency across linker and evaluator.
func EffectRowDifference ¶
EffectRowDifference returns the effects in 'a' that are not in 'b' Result is sorted alphabetically
func EvalNot ¶ added in v0.14.3
EvalNot evaluates the refinement predicate {not ℓ} against label L. Returns true iff ℓ is NOT subsumed by L (i.e., the argument is safe for a {not ℓ} sink).
func ExtractTVarName ¶
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 ¶
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 ¶
IsGroundType checks if a type contains no type variables This is used to verify that types are fully resolved before elaboration
func IsKnownEffect ¶
IsKnownEffect checks if an effect name is one of the canonical effects
func IsOpenRecord ¶
IsOpenRecord checks if a record type is open (has row variable)
func IsTVar ¶
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 LabelEqual ¶ added in v0.14.3
LabelEqual reports whether two labels are structurally equal after normalisation.
func LabelSubsumes ¶ added in v0.14.3
LabelSubsumes reports whether label ℓ appears (by name) anywhere in L's join. Semantics: "L is tainted with at least ℓ".
func MakeDictionaryKey ¶
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 MarshalLabel ¶ added in v0.14.3
MarshalLabel serialises a Label to JSON. nil is serialised as ⊥ for backwards compatibility with ifaces that omit the field.
func MarshalScheme ¶
MarshalScheme serializes a Scheme to JSON.
func NormalizeTypeName ¶
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 ¶
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 ¶
ParseDictionaryKey extracts components from a dictionary key Now uses :: separator for better visual clarity
func RecordHasField ¶
RecordHasField checks if a record type has a specific field
func SafeEquals ¶
SafeEquals compares two types for equality with cycle detection This prevents infinite loops when comparing cyclic type graphs
func SafeTypeString ¶
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 ¶
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 ¶
TruncatedTypeString returns a string representation that's guaranteed to be short. Useful for error messages and logging where space is limited.
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 (*Builder) App ¶
App creates a type application (e.g., List<String>, Result<T, E>) For higher-kinded types like Result<Response, NetError>
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) List ¶
List creates a list type: list[T] Uses lowercase "list" to match AILANG syntax
func (*Builder) Rec ¶
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())
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 ¶
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 ¶
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.
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 DeclassError ¶ added in v0.14.3
DeclassError is returned when a function changes a value's label without the Declassify capability in its effect row.
func CheckDeclassify ¶ added in v0.14.3
func CheckDeclassify(inputLabel, outputLabel Label, effectRow []string) *DeclassError
CheckDeclassify verifies that a function is not silently changing the label of a value between its input and output without the Declassify capability.
Rule (DECLASS): if inputLabel ≠ outputLabel (and they are not equal label variables), the effect row MUST contain "Declassify".
Identity functions (same label variable or same constant) do not require Declassify. ⊥-to-⊥ functions (plain unlabelled code) also do not require Declassify.
func (*DeclassError) Error ¶ added in v0.14.3
func (e *DeclassError) Error() string
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 ¶
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 (*EffectVar) Equals ¶
func (e *EffectVar) Equals(other EffectType) bool
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) 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 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 Kind ¶
type Kind interface {
String() string
Equals(Kind) bool
// contains filtered or unexported methods
}
Kind represents kinds in the type system
func ExtractTVarKind ¶
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 UnmarshalKind ¶
UnmarshalKind deserializes a Kind from JSON.
type Label ¶ added in v0.14.3
type Label interface {
String() string
// contains filtered or unexported methods
}
Label represents an information-flow label in the lattice:
L ::= ⊥ | ℓ | α | L₁ ⊔ L₂
The zero value of the interface is not valid; always use the constructors.
func JoinLabelList ¶ added in v0.14.3
JoinLabelList returns the join of labels across a slice of types.
func JoinLabels ¶ added in v0.14.3
JoinLabels returns the join of the labels carried by two types. Used for match-arm joins, record construction, and let-binding propagation.
func LabelBottom ¶ added in v0.14.3
func LabelBottom() Label
LabelBottom returns the bottom element ⊥.
func LabelConst ¶ added in v0.14.3
LabelConst returns a constant label with the given name.
func LabelJoin ¶ added in v0.14.3
LabelJoin returns the least upper bound L1 ⊔ L2 with simplification:
- ⊥ is the identity element
- idempotence: L ⊔ L = L
- the result is normalised to a sorted, flattened, deduplicated join
func LabelOf ¶ added in v0.14.3
LabelOf returns the IFC label carried by t, or ⊥ if t is unlabelled.
func PurePropagateLabel ¶ added in v0.14.3
PurePropagateLabel computes the output label for a pure function application. Rule (APP-PURE): output label = returnLabel ⊔ join(LabelOf(arg) for each arg)
func UnmarshalLabel ¶ added in v0.14.3
UnmarshalLabel deserialises a Label from JSON. Empty/null/missing data returns ⊥ for backwards compatibility with pre-label ifaces.
type MissingInstanceError ¶
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) OnFreshTypeVar ¶
func (NoOpDebugSink) OnFreshTypeVar(Type, uint64, OriginKind)
func (NoOpDebugSink) OnSubstitute ¶
func (NoOpDebugSink) OnSubstitute(Type, Type)
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)
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 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 ¶
CanonicalizeRow returns the canonical representation of a row
func ElaborateEffectRow ¶
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 UnionEffectRows ¶
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 ¶
UnionEffects computes the union of multiple effect rows
func (*Row) MarshalJSON ¶
type RowUnifier ¶
type RowUnifier struct {
// contains filtered or unexported fields
}
RowUnifier handles row unification with principal types
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 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 ¶
UnmarshalScheme deserializes a Scheme from JSON.
func (*Scheme) Instantiate ¶
Instantiate creates a fresh instance of the type scheme
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 SinkError ¶ added in v0.14.3
type SinkError struct {
ArgLabel Label // the label carried by the argument
SinkLabel string // the label name forbidden by the sink ({not SinkLabel})
}
SinkError is returned when a labelled value reaches a sink that forbids its label. The sink is a parameter annotated with T{not LABEL}.
func CheckSinkRefinement ¶ added in v0.14.3
func CheckSinkRefinement(argType Type, refinement *ast.RefinementExpr) *SinkError
CheckSinkRefinement verifies that argType's label satisfies refinement. Returns a *SinkError if the argument's label is subsumed by the forbidden label, or nil if the check passes (including when refinement is nil).
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 ¶
Substitution maps variable names to types
func ComposeSubstitutions ¶
func ComposeSubstitutions(s1, s2 Substitution) Substitution
ComposeSubstitutions composes two substitutions
type TArray ¶
type TArray struct {
Element Type
}
TArray represents an array type with O(1) indexed access
func (*TArray) MarshalJSON ¶
type TCon ¶
type TCon struct {
Name string
}
TCon represents a type constructor (int, bool, string, etc.)
func (*TCon) MarshalJSON ¶
type TLabelled ¶ added in v0.14.3
TLabelled wraps any Type with an information-flow label. Use WithLabel / LabelOf / StripLabel rather than constructing directly.
func (*TLabelled) MarshalJSON ¶ added in v0.14.3
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) MarshalJSON ¶
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 ¶
TRecord2ToTRecord converts new TRecord2 to old TRecord (for compatibility)
func (*TRecord) MarshalJSON ¶
type TRecord2 ¶
type TRecord2 struct {
Row *Row // Row of kind KRow(KRecord)
}
TRecord2 represents a record type with row
func TRecordToTRecord2 ¶
TRecordToTRecord2 converts old TRecord to new TRecord2
func (*TRecord2) MarshalJSON ¶
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) MarshalJSON ¶
type TVar ¶
type TVar struct {
Name string
}
TVar represents a type variable
func (*TVar) MarshalJSON ¶
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 ¶
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 RecordFieldType ¶
RecordFieldType gets the type of a field in a record
func RecordSelection ¶
RecordSelection checks if a record type has a field and returns its type
func StripLabel ¶ added in v0.14.3
StripLabel removes the TLabelled wrapper, returning the underlying type.
func UnmarshalType ¶
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 (*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 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 ¶
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 ¶
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) ExtendScheme ¶
ExtendScheme creates a new environment with a scheme binding
func (*TypeEnv) FreeRowVars ¶
FreeRowVars returns all free row variables in the environment
func (*TypeEnv) FreeTypeVars ¶
FreeTypeVars returns all free type variables in the environment
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
func Head ¶
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)
type TypeInfo ¶
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 (TypeInfo) Get ¶
Get returns the type for the given expression and a boolean indicating if it was found
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 ¶
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 TypedExpression ¶
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 ¶
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 NewUnifierWithAliases ¶
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).
Source Files
¶
- builder.go
- cycles.go
- debug_sink.go
- defaulting.go
- dictionaries.go
- effects.go
- env.go
- errors.go
- gob.go
- helpers.go
- inference.go
- inference_helpers.go
- instances.go
- json.go
- kinds.go
- label_helpers.go
- label_json.go
- labels.go
- normalize.go
- pool.go
- row_unification.go
- safe_string.go
- sink_check.go
- type_head.go
- type_report.go
- typechecker.go
- typechecker_core.go
- typechecker_data.go
- typechecker_defaulting.go
- typechecker_functions.go
- typechecker_literals.go
- typechecker_operators.go
- typechecker_patterns.go
- typechecker_substitution.go
- typeinfo.go
- types.go
- types_v2.go
- unification.go
- unification_core.go
- unification_equality.go
- unification_occurs.go
- unification_records.go
- unification_substitution.go
- unification_types.go