fix(mir): Phase 131-9 - PHI 型推論修正(String→Integer)
Phase 131-9: MIR PHI 型推論バグ修正 問題: - PHI が String 型として推論される - 結果: 0,01,011(文字列連結) - 期待: 0,1,2(整数 increment) 根本原因: - PHI emission 時に circular dependency - latch incoming value が PHI 型を継承 - 使用側(print)の型要求で String に 修正: - src/mir/builder/lifecycle.rs (+75 lines): - Global PHI Type Inference Pass 追加 - PHI 型を incoming values から再推論 - PhiTypeResolver を再利用 MIR 変化: - Before: %3: String = phi [%2, bb0], [%12, bb7] - After: %3: Integer = phi [%2, bb0], [%12, bb7] テスト結果: - Rust VM: 0,01,011 → 0,1,2 ✅ 完璧! - LLVM: Segfault(別バグ、Phase 131-10 で対応) 箱化モジュール化: - ✅ PhiTypeResolver 再利用 - ✅ 単一責任: PHI 型補正のみ - ✅ Debug flag: NYASH_PHI_GLOBAL_DEBUG=1 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -307,13 +307,88 @@ impl super::MirBuilder {
|
||||
|
||||
let mut module = self.current_module.take().unwrap();
|
||||
let mut function = self.current_function.take().unwrap();
|
||||
function.metadata.value_types = self.value_types.clone();
|
||||
// Phase 84-2: Copy命令型伝播(return型推論の前に実行)
|
||||
//
|
||||
// Loop exit や If merge の edge copy で発生する型欠如を解消する。
|
||||
// Copy チェーン: v1 → v2 → v3 で v1 の型が既知なら v2, v3 にも伝播。
|
||||
CopyTypePropagator::propagate(&function, &mut self.value_types);
|
||||
|
||||
// Phase 131-9: Global PHI type inference
|
||||
//
|
||||
// Infer types for ALL PHI nodes, not just return values.
|
||||
// This fixes loop carrier PHIs that don't get inferred otherwise.
|
||||
// Uses PhiTypeResolver to infer from incoming values (not usage).
|
||||
//
|
||||
// Bug: loop_min_while.hako PHI %3 was typed as String instead of Integer
|
||||
// Cause: PHI incoming values unavailable at emission time
|
||||
// Fix: Run PhiTypeResolver after CopyTypePropagator, before return type inference
|
||||
//
|
||||
// Collect ALL PHI dsts for re-inference (not just untyped)
|
||||
// This is necessary because propagate_phi_meta may have assigned incorrect types
|
||||
// due to circular dependencies (e.g., loop carrier PHIs)
|
||||
let mut all_phi_dsts: Vec<ValueId> = Vec::new();
|
||||
for (_bid, bb) in function.blocks.iter() {
|
||||
for inst in &bb.instructions {
|
||||
if let MirInstruction::Phi { dst, .. } = inst {
|
||||
if std::env::var("NYASH_PHI_GLOBAL_DEBUG").is_ok() {
|
||||
let existing_type = self.value_types.get(dst);
|
||||
eprintln!(
|
||||
"[lifecycle/phi-scan] {} PHI {:?} existing type: {:?}",
|
||||
function.signature.name, dst, existing_type
|
||||
);
|
||||
}
|
||||
all_phi_dsts.push(*dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if std::env::var("NYASH_PHI_GLOBAL_DEBUG").is_ok() {
|
||||
eprintln!(
|
||||
"[lifecycle/phi-scan] {} found {} total PHIs to re-infer",
|
||||
function.signature.name,
|
||||
all_phi_dsts.len()
|
||||
);
|
||||
}
|
||||
|
||||
// Re-infer types for ALL PHI nodes using PhiTypeResolver
|
||||
// This fixes incorrect types assigned by propagate_phi_meta during circular dependencies
|
||||
if !all_phi_dsts.is_empty() {
|
||||
let phi_resolver = PhiTypeResolver::new(&function, &self.value_types);
|
||||
let mut inferred_types: Vec<(ValueId, MirType)> = Vec::new();
|
||||
for dst in all_phi_dsts {
|
||||
if let Some(mt) = phi_resolver.resolve(dst) {
|
||||
// Check if type changed
|
||||
let existing_type = self.value_types.get(&dst);
|
||||
if existing_type.is_none() || existing_type != Some(&mt) {
|
||||
inferred_types.push((dst, mt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now insert/update all inferred types
|
||||
for (dst, mt) in inferred_types {
|
||||
let old_type = self.value_types.get(&dst).cloned();
|
||||
self.value_types.insert(dst, mt.clone());
|
||||
if std::env::var("NYASH_PHI_GLOBAL_DEBUG").is_ok() {
|
||||
if let Some(old) = old_type {
|
||||
eprintln!(
|
||||
"[lifecycle/phi-global] {} PHI {:?} type corrected: {:?} -> {:?}",
|
||||
function.signature.name, dst, old, mt
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
"[lifecycle/phi-global] {} PHI {:?} type inferred: {:?}",
|
||||
function.signature.name, dst, mt
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Phase 131-9: Update function metadata with corrected types
|
||||
// MUST happen after PHI type correction above
|
||||
function.metadata.value_types = self.value_types.clone();
|
||||
|
||||
// Phase 82-5: lifecycle.rs バグ修正 - terminator の Return のみをチェック
|
||||
// 問題: instructions を先に走査すると、中間値(const void 等)を誤って推論対象にしてしまう
|
||||
// 解決: terminator の Return のみをチェックし、実際の戻り値を正しく推論する
|
||||
|
||||
Reference in New Issue
Block a user