fix(mir): evaluate machine when-guards and trap-close the fallthrough#2390
Merged
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Machine
whenguards 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 handlingemit_machine_step_transition_returnalready 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
defaultarm 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 realTrapKind::ExhaustivenessFallthroughtrap instead of a bare LLVMunreachable. 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
Closed{code:1}machine with==42/!=42guarded arms fired the wrong (Open) arm before the fix; after the fix it correctly falls through to the!=42arm.Closed{code:42}→Open), proving the guard is evaluated both ways, not just gated shut.defaultnow traps cleanly (hew: trap in main context: Trap, non-zero exit, no signal) instead of hitting UB.hew-codegen-rsexec tests: IR-shape assertions split intohas_default/has_guard/ neither, asserting the guard-bearing fallthrough emits the real trap call (not a bareunreachable); execution tests for all four new fixtures including the fallthrough-trap oracle.cargo test -p hew-mirandcargo test -p hew-codegen-rsgreen;cargo fmtandcargo clippy -- -D warningsclean on both crates.Out of scope
None.