← All posts

Cure v0.13.0: The Type System Grows Teeth

by Aleksei Matiushkin

release dependent-types protocols optimizer

v0.12 gave Cure a body. v0.13 gives it teeth.

The headline: when you write fn safe_divide(a: Int, b: Int) -> Int when b != 0, the compiler now actually checks that constraint at every call site. Call safe_divide(10, 0) and Z3 proves the violation before a single BEAM instruction runs. Call safe_divide(10, x) where x came from user input and the compiler tells you it cannot prove the constraint – your job to handle it.

This is not a runtime check. This is a compile-time proof.

What changed

Seven things, each deepening a subsystem that v0.12 established.

1. Dependent type verification

Functions with when guards now register as constrained types:

fn safe_divide(a: Int, b: Int) -> Int when b != 0 = a / b
fn positive_double(x: Int) -> Int when x > 0 = x * 2

At call sites, the compiler substitutes literal arguments into the guard predicate and sends it to Z3. If the predicate is unsatisfiable after substitution, you get a warning with a counterexample from the solver.

2. Protocols that cross module boundaries

Every impl is registered in a global ETS table during compilation. When you compile Std.Show, the registry learns that :std_show provides show/1 for Int, Float, String, Bool, and Atom. This is the foundation for cross-module dispatch.

3. LSP improvements

Go-to-definition, document symbols (hierarchical outline), and code actions: quick-fix for non-exhaustive matches and did-you-mean suggestions for unbound variables.

4. Five optimizer passes

Inline (small pure non-recursive functions), constant fold, dead code elimination, pipe chain inline, and guard simplification (algebraic boolean rules).

5. FSM guards and actions

Transitions now support when guards and do actions:

fsm Counter
  Counting --tick when count > 0 do count = count - 1--> Counting
  Counting --tick when count == 0--> Done

6. Structured errors with source context

Error codes E001-E005, source line display with caret, cure explain E001.

7. Four new stdlib modules

Std.Map (14 fns), Std.Set (11 fns), Std.Option (10 fns), Std.Functor (1 fn). Total: 17 modules, ~200 functions.

The numbers

606 tests. Zero credo issues. Zero compilation warnings. 48 Elixir source files.

The repository is at github.com/am-kantox/cure.