Skip to content

fix(mir): evaluate machine when-guards and trap-close the fallthrough#2390

Merged
slepp merged 5 commits into
mainfrom
fix/machine-when-guards
Jul 4, 2026
Merged

fix(mir): evaluate machine when-guards and trap-close the fallthrough#2390
slepp merged 5 commits into
mainfrom
fix/machine-when-guards

Conversation

@slepp

@slepp slepp commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Machine when guards were type-checked but never evaluated at runtime: synthesize_machine_step_fn's event cascade branched on event-tag equality only, so a guarded transition fired regardless of whether its guard held. I added a guard-check block between the event-eq branch and the arm body, reusing the same self/event binding-env handling emit_machine_step_transition_return already uses, evaluated before any hook or transition-out drop — a false guard now falls through to the next arm exactly like an event mismatch would.

This also closes a latent undefined-behaviour hole: once a guard can evaluate false at runtime, an all-guards-false step with no default arm is a genuinely reachable, user-visible condition rather than the dead code HIR exhaustiveness used to guarantee. I route any machine with at least one guarded transition to a real TrapKind::ExhaustivenessFallthrough trap instead of a bare LLVM unreachable. Guard-free machines are unaffected — they keep the existing (sound) unreachable, since an event match still fires unconditionally there and HIR exhaustiveness proves the fallthrough unreachable.

Verification

  • Red-before/green-after: a Closed{code:1} machine with ==42/!=42 guarded arms fired the wrong (Open) arm before the fix; after the fix it correctly falls through to the !=42 arm.
  • A true guard still fires (Closed{code:42}Open), proving the guard is evaluated both ways, not just gated shut.
  • An all-guards-false step with no default now traps cleanly (hew: trap in main context: Trap, non-zero exit, no signal) instead of hitting UB.
  • New hew-codegen-rs exec tests: IR-shape assertions split into has_default / has_guard / neither, asserting the guard-bearing fallthrough emits the real trap call (not a bare unreachable); execution tests for all four new fixtures including the fallthrough-trap oracle.
  • cargo test -p hew-mir and cargo test -p hew-codegen-rs green; cargo fmt and cargo clippy -- -D warnings clean on both crates.
  • Full test corpus and o2-differential green in an integrated build alongside unrelated in-flight work; no regressions.

Out of scope

None.

slepp added 4 commits July 3, 2026 17:44
synthesize_machine_step_fn's event cascade branched on event-tag equality
only; transition.guard was type-checked but never read, so a guarded
transition fired regardless of the guard's runtime value (silent-wrong
routing). A guarded arm now inserts a guard-check block between the
event-eq branch and the arm body, reusing the exact self/event
binding-env dance emit_machine_step_transition_return uses, evaluated
before any hook or transition-out drop. A false guard falls through to
the next arm exactly like an event mismatch would.

This makes the no-default dispatch fallthrough a genuinely reachable,
user-visible condition once a guard can evaluate false at runtime
(an all-guards-false step), rather than the HIR-exhaustiveness-proven
dead code it used to be. Reaching the fallthrough's bare LLVM
unreachable would now be undefined behaviour. Route any machine with
at least one guarded transition to a real TrapKind::ExhaustivenessFallthrough
trap instead; guard-free machines keep today's unreachable.
Remove G-M1 shorthand and fence-item terminology from comments,
rephrasing to plain technical invariants:
- examples/machine/guard_fallthrough_traps.hew line 4
- examples/machine/guard_gates_transition.hew line 3
- hew-codegen-rs/tests/exec/machine_exec.rs lines 22, 66, 75, 84, 365, 487

Comment prose only — no code or test logic changed.
@slepp slepp enabled auto-merge (squash) July 4, 2026 03:45
@slepp slepp merged commit 762a728 into main Jul 4, 2026
12 checks passed
@slepp slepp deleted the fix/machine-when-guards branch July 4, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant