Add type inference infrastructure

Introduces a `TypeChecker` struct with logic for Hindley-Milner type
inference.
This includes:
- `var_counter` for generating unique type variable IDs.
- `subst` for the global substitution map.
- `fresh_var` to create new type variables.
- `apply_subst` to resolve type variables recursively.
- `occurs` to check for cycles during unification.
- `unify` to merge types and extend the substitution.

The `StaticType` enum is extended with a `TypeVar(u32)` variant to
represent unresolved type variables.
The `Display` and `is_assignable_from` implementations for `StaticType`
are updated to handle `TypeVar`.
This commit is contained in:
2026-03-28 13:08:15 +01:00
parent 982d2239b6
commit e595e747d4
2 changed files with 126 additions and 1 deletions
+7
View File
@@ -373,6 +373,9 @@ pub enum StaticType {
resolve_return: fn(&StaticType) -> Option<StaticType>,
resolve_arg_hints: Option<ArgHintResolver>,
},
/// An unresolved type variable used during Hindley-Milner type inference.
/// The `u32` is a unique ID assigned by the type checker. Resolved via substitution.
TypeVar(u32),
/// A diagnostic poison type, allowing type-checking to continue after an error.
Error,
}
@@ -432,6 +435,7 @@ impl fmt::Display for StaticType {
}
StaticType::Object(name) => write!(f, "{}", name),
StaticType::PolymorphicFn { .. } => write!(f, "<polymorphic-fn>"),
StaticType::TypeVar(n) => write!(f, "?{}", n),
StaticType::Error => write!(f, "<error>"),
}
}
@@ -479,6 +483,8 @@ impl StaticType {
|| matches!(other, StaticType::Any)
|| matches!(self, StaticType::Error)
|| matches!(other, StaticType::Error)
|| matches!(self, StaticType::TypeVar(_))
|| matches!(other, StaticType::TypeVar(_))
{
return true;
}
@@ -589,6 +595,7 @@ impl StaticType {
.or_else(|| sigs.iter().find(|sig| sig.params.is_assignable_from(args_ty))) // 2. Fallback to implicit coercion
.map(|sig| sig.ret.clone()),
StaticType::PolymorphicFn { resolve_return, .. } => resolve_return(args_ty),
StaticType::TypeVar(_) => Some(StaticType::Any),
_ => None,
}
}