Highlights
- First-order unification with an occurs check, so a variable can never be bound to a type that contains itself. The substitution produced is a most-general unifier.
- Language-agnostic type representation: constructors are opaque tags the consumer assigns meaning to, so the same core expresses primitives, generics, functions, and tuples.
- Iterative core — unification and the occurs check use explicit work stacks, so a deeply nested type cannot overflow the call stack.
no_std-friendly (needs onlyalloc), with optionalserdefor serialising type terms and inference state.- No panics in shipping code; every failure is a defined
TypeError.#![forbid(unsafe_code)].
Installation
[]
= "1.0"
Usage
A consumer assigns meaning to constructor tags, then unifies the types it builds. Unification discovers what the inference variables must be:
use ;
// The consumer's constructor table — the tags are arbitrary but stable.
const FUNCTION: TyCon = new;
const INT: TyCon = new;
const BOOL: TyCon = new;
let mut unifier = new;
let arg = unifier.fresh;
let ret = unifier.fresh;
// A call site needs a function (?arg) -> ?ret; the callee is (int) -> bool.
let needed = app;
let callee = app;
unifier.unify.expect;
// Unification solved both variables.
assert_eq!;
assert_eq!;
Failures are values, not panics — a mismatch carries the clashing types, and a self-referential type is rejected by the occurs check:
use ;
const INT: TyCon = new;
const LIST: TyCon = new;
let mut unifier = new;
// Different constructors do not unify.
let err = unifier.unify.unwrap_err;
assert!;
// ?v = List<?v> would be an infinite type.
let v = unifier.fresh;
let recursive = app;
let err = unifier.unify.unwrap_err;
assert!;
See docs/API.md for the full reference.
Feature flags
| Feature | Default | Description |
|---|---|---|
std |
yes | Builds against the standard library. With default-features = false the crate is no_std (it always needs alloc); the full API works unchanged. |
serde |
no | Derives Serialize / Deserialize for Type, TyVar, TyCon, and Unifier. |
Contributing
See dev/DIRECTIVES.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.