fix(mir/phi): include pinned variables in loop header PHIs

**Problem**: "use of undefined value ValueId(22)" errors in Stage-B
when method receivers were used after loops.

**Root cause**: prepare_loop_variables_with() explicitly skipped
pinned variables (like __pin$6438$@recv) when creating loop header
PHIs. Comment claimed they were "materialized via entry-phi in loop
body" but this only happened for the body block, not for loop exit
merge points. When receivers were used after loops, there was no PHI
to merge values from different control flow paths.

**Fix**: Remove the skip logic (lines 174-177) so pinned variables
get PHIs at loop headers and exits like any other variable.

**Impact**:
- ValueId(22) error eliminated in Stage-B selfhost tests
- MIR verification passes with NYASH_VM_VERIFY_MIR=1
- Pinned slots now correctly merge across loop boundaries
- No more "use of undefined value" for cross-loop receivers

**Test case**: /tmp/test_loop_recv.hako demonstrates receiver usage
in loop and after loop exit, now works correctly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-17 02:16:59 +09:00
parent eadde8d1dd
commit 116ff105ed

View File

@ -170,11 +170,10 @@ pub fn prepare_loop_variables_with<O: LoopPhiOps>(
let mut incomplete_phis: Vec<IncompletePhi> = Vec::new();
for (var_name, &value_before) in current_vars.iter() {
// Skip pinned variables (internal compiler temporaries)
if var_name.starts_with("__pin$") {
// Pinned variables are materialized via entry-phi in loop body, skip here
continue;
}
// Phase 25.1b fix: Include pinned variables in loop header PHIs
// Previously pinned variables were skipped, causing "use of undefined value"
// errors when receivers were used after loops. Pinned variables need PHIs
// at both header and exit points to properly merge values across control flow.
// Materialize the incoming value at preheader to satisfy UseBeforeDef constraints
// even when `value_before` was defined in a different block (e.g., previous loop header).