Explanation
Inference Proof Sketch
Understand the design decisions, alternatives, and limits.
The checker is not a formal proof assistant, but its structure follows the standard progress path for a typed language: every accepted expression receives a type, and every emitted call has a statically established arity and value representation. The proof obligation is limited by OJaml's uniform WebAssembly ABI: values travel through i32 parameters and results, with compiler-side int/float specialization where polymorphic functions need different concrete representations at different call sites.
Soundness here means the compiler never emits direct WebAssembly for a program with unresolved names, inconsistent branches, impossible call arity, or collection access whose key/value relationship is statically contradictory. Runtime helpers also trap invalid collection access such as out-of-bounds array reads, empty-list head/tail, and missing map keys. This is still not a full safety proof for every pointer operation: garbage collection and recoverable language-level exceptions are outside the current core.
The reconstruction hinge is preservation under unification: once two types are unified, all later pruned references see the same representative. Local hover information stays accurate because a binding span and every later use point at type graph nodes that resolve through the same pruning path.
- Base cases assign primitive types to literals.
- Inductive expression cases add local constraints and unify recursively checked subexpressions.
- Function cases introduce fresh parameter variables and infer the body under the extended environment.
- Match cases unify every pattern with the scrutinee and every arm body with a shared result.