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:
@@ -863,6 +863,20 @@ impl<'a> Emitter<'a> {
|
||||
Literal::Unit => ("0".into(), "i8".into()),
|
||||
}),
|
||||
Term::Var { name } => {
|
||||
// Iter 16d: `__unreachable__` is a polymorphic bottom
|
||||
// value (`forall a. a`). At codegen we emit LLVM
|
||||
// `unreachable` as the block terminator and return a
|
||||
// dummy SSA value. The surrounding `if`/`match`/`seq`
|
||||
// already inspects `block_terminated` and forwards the
|
||||
// sibling branch's type, so the type we report here is
|
||||
// not consumed by a phi node — `i8` is a sound
|
||||
// placeholder. Subsequent emissions in this block are
|
||||
// gated by `block_terminated`.
|
||||
if name == "__unreachable__" {
|
||||
self.body.push_str(" unreachable\n");
|
||||
self.block_terminated = true;
|
||||
return Ok(("0".into(), "i8".into()));
|
||||
}
|
||||
if let Some((_, ssa, ty, _)) =
|
||||
self.locals.iter().rev().find(|(n, _, _, _)| n == name)
|
||||
{
|
||||
@@ -2632,6 +2646,12 @@ fn builtin_ail_type(name: &str) -> Option<Type> {
|
||||
ret: Box::new(Type::bool_()),
|
||||
effects: vec![],
|
||||
},
|
||||
// Iter 16d: `__unreachable__` is the polymorphic bottom value
|
||||
// (`forall a. a`). Mirrors the typechecker's `builtins::install`.
|
||||
"__unreachable__" => Type::Forall {
|
||||
vars: vec!["a".into()],
|
||||
body: Box::new(Type::Var { name: "a".into() }),
|
||||
},
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user