Iter 16d: chain-terminator via __unreachable__ builtin

Eliminates the Unit-typed chain default that 16c left in place.
Adds __unreachable__ : forall a. a — codegen lowers to LLVM
unreachable. The 16a/16c chain machinery now uses it as the
deepest fall-through, so exhaustive matches with non-Unit arms
no longer need a (case _ ...) workaround.

- check/builtins.rs: register __unreachable__ as Forall(a, a).
- codegen: Term::Var "__unreachable__" emits LLVM unreachable
  and sets block_terminated; If/Match/fn-body gate downstream
  work on that flag.
- desugar: chain default switched from Lit{Unit} to Var.
- examples/lit_pat: categorize_first's trailing _ arm removed.
  Hash changes from c4faec3abc2ed388 to 644de0c0ec15fc17.
- examples/unreachable_demo: positive fixture using safe_div
  with __unreachable__ in the impossible branch.
- e2e + desugar tests: 122 → 124 (+2).

Path-a from 16b.2 planning: real primitive over a desugar-time
exhaustiveness pre-check (which would need cross-module type
registry access from desugar).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 23:00:23 +02:00
parent e5f9828a04
commit af35612c1d
10 changed files with 353 additions and 14 deletions
+22
View File
@@ -1109,9 +1109,31 @@ fn check_json_unbound_var() {
/// either a wrong result or an `unreachable!` panic depending on
/// the path. The fixture exercises both sites: `classify` (top-
/// level lit arms) and `categorize_first` (nested lit-in-Ctor).
///
/// Iter 16d update: the trailing `(case _ 0)` arm of
/// `categorize_first` was removed when the chain machinery's
/// terminator switched from a `Unit` literal to the polymorphic
/// `__unreachable__` builtin. Output is unchanged — this test
/// guards both 16c (lit-pattern desugar) and 16d (no-workaround
/// chain default).
#[test]
fn lit_pat_demo() {
let stdout = build_and_run("lit_pat.ail.json");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["100", "200", "999", "-1", "0", "7"]);
}
/// Iter 16d: `__unreachable__` as an explicit user-callable
/// primitive. Property protected: a polymorphic `forall a. a` value
/// reference (a) typechecks against any expected type at the use
/// site (here `Int`), and (b) codegen lowers it to LLVM
/// `unreachable`, with the surrounding `if` correctly forwarding
/// the live branch's value past the terminated branch. The fixture
/// only ever hits the live branch, so the binary must succeed and
/// print the expected outputs.
#[test]
fn unreachable_demo() {
let stdout = build_and_run("unreachable_demo.ail.json");
let lines: Vec<&str> = stdout.lines().collect();
assert_eq!(lines, vec!["4", "5"]);
}