fix(mir): fix else block scope bug - PHI materialization order
Root Cause: - Else blocks were not propagating variable assignments to outer scope - Bug 1 (if_form.rs): PHI materialization happened before variable_map reset, causing PHI nodes to be lost - Bug 2 (phi.rs): Variable merge didn't check if else branch modified variables Changes: - src/mir/builder/if_form.rs:93-127 - Reordered: reset variable_map BEFORE materializing PHI nodes - Now matches then-branch pattern (reset → materialize → execute) - Applied to both "else" and "no else" branches for consistency - src/mir/builder/phi.rs:137-154 - Added else_modified_var check to detect variable modifications - Use modified value from else_var_map_end_opt when available - Fall back to pre-if value only when truly not modified Test Results: ✅ Simple block: { x=42 } → 42 ✅ If block: if 1 { x=42 } → 42 ✅ Else block: if 0 { x=99 } else { x=42 } → 42 (FIXED!) ✅ Stage-B body extraction: "return 42" correctly extracted (was null) Impact: - Else block variable assignments now work correctly - Stage-B compiler body extraction restored - Selfhost builder path can now function - Foundation for Phase 21.x progress 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -93,22 +93,35 @@ impl MirBuilder {
|
||||
self.debug_push_region(format!("join#{}", join_id) + "/else");
|
||||
// Scope enter for else-branch
|
||||
self.hint_scope_enter(0);
|
||||
// Materialize all variables at block entry via single-pred Phi (correctness-first)
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.insert_phi_single(pre_branch_bb, pre_v)?;
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
if trace_if {
|
||||
eprintln!(
|
||||
"[if-trace] else-entry phi var={} pre={:?} -> dst={:?}",
|
||||
name, pre_v, phi_val
|
||||
);
|
||||
}
|
||||
}
|
||||
let (else_value_raw, else_ast_for_analysis, else_var_map_end_opt) = if let Some(else_ast) = else_branch {
|
||||
// Reset variable_map BEFORE materializing PHI nodes (same pattern as then-branch)
|
||||
self.variable_map = pre_if_var_map.clone();
|
||||
// Materialize all variables at block entry via single-pred Phi (correctness-first)
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.insert_phi_single(pre_branch_bb, pre_v)?;
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
if trace_if {
|
||||
eprintln!(
|
||||
"[if-trace] else-entry phi var={} pre={:?} -> dst={:?}",
|
||||
name, pre_v, phi_val
|
||||
);
|
||||
}
|
||||
}
|
||||
let val = self.build_expression(else_ast.clone())?;
|
||||
(val, Some(else_ast), Some(self.variable_map.clone()))
|
||||
} else {
|
||||
// No else branch: materialize PHI nodes for the empty else block
|
||||
self.variable_map = pre_if_var_map.clone();
|
||||
for (name, &pre_v) in pre_if_var_map.iter() {
|
||||
let phi_val = self.insert_phi_single(pre_branch_bb, pre_v)?;
|
||||
self.variable_map.insert(name.clone(), phi_val);
|
||||
if trace_if {
|
||||
eprintln!(
|
||||
"[if-trace] else-entry phi var={} pre={:?} -> dst={:?}",
|
||||
name, pre_v, phi_val
|
||||
);
|
||||
}
|
||||
}
|
||||
let void_val = crate::mir::builder::emission::constant::emit_void(self);
|
||||
(void_val, None, None)
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user