Files
hakorune/docs/development/current/main/phase84-case-d-detailed-analysis.md
nyash-codex 4ef5eec162 feat(mir): Phase 84-2 CopyTypePropagator for Copy chain type propagation
- Add CopyTypePropagator box (ChatGPT Pro design) for fixed-point
  Copy instruction type propagation
- Integrate into lifecycle.rs before return type inference
- Case D reduced from 12 to 9 (25% reduction)

Implementation:
- src/mir/phi_core/copy_type_propagator.rs: New box with fixed-point loop
- src/mir/phi_core/mod.rs: Add module export
- src/mir/builder/lifecycle.rs: Call propagator before return inference

Test results:
- Baseline: 494 passed, 33 failed (was 489/34)
- Case D: 9 remaining (from 12)
- Unit tests: 4/4 passed

Remaining 9 Case D breakdown:
- GroupA: Loop Edge Copy (7 cases) - PHI incoming needs Copy trace
- GroupB: Multi-level PHI (2 cases) - Recursive PHI resolution needed

Phase 84-3 will address GroupA with Edge Copy tracing in GenericTypeResolver.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 19:37:01 +09:00

12 KiB
Raw Blame History

Phase 84: Case D 詳細分析レポート

概要

Phase 83 で Case D が 20 件 → 15 件 に減少MethodReturnHintBox 実装)。
その後 Phase 84-1Const 命令型アノテーション追加)で 12 件、Phase 84-2CopyTypePropagator 導入)で 9 件 まで削減された。

本レポート自体は「24 件あった調査時点」の分析ログとして残しつつ、
現在は Const 欠如グループと単純な Copy チェーンは解消され、残りは主に PHI を含む複雑なパターンであることが判明している。

重要な発見(当時): 主要な原因は Const命令の型アテーション欠如 である。
補足(現在): Const 命令については 40dfbc68 で修正済み、Copy 伝播については CopyTypePropagatorPhase 84-2で整理済み。


実行環境

NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1

テスト結果(当時): 471 passed; 52 failed (うち Case D は24件)


Case D 失敗一覧24件

# Test Name Function ValueId 推測される原因
1 test_lowering_await_expression main ValueId(2) Await式の戻り値型
2 test_try_catch_compilation main ValueId(7) Try-Catch式の戻り値型
3 loop_break_and_early_return_edge_copy main ValueId(50) Loop exit後の型
4 loop_with_continue_and_break_edge_copy_merge main ValueId(56) Loop exit後の型
5 vm_exec_break_inside_if main ValueId(27) Loop break後の型
6 mir_locals_uninitialized main ValueId(1) return 0 の型
7 loop_inner_if_multilevel_edge_copy main ValueId(74) Loop exit後の型
8 nested_loop_with_multi_continue_break_edge_copy_merge main ValueId(135) Loop exit後の型
9 mir13_no_phi_if_merge_inserts_edge_copies_for_return main ValueId(17) If merge後の型
10 loop_if_three_level_merge_edge_copy main ValueId(75) Loop exit後の型
11 nested_if_inside_loop_edges_copy_from_exiting_blocks main ValueId(6) Loop exit後の型
12 nested_loops_break_continue_mixed main ValueId(8) Loop exit後の型
13 mir_funcscanner_skip_ws_min_verify_and_vm main ValueId(76) 複雑な制御フロー
14-20 mir_stageb_like_*_verifies main ValueId(1) return 系の型
21 mir_stage1_cli_emit_program_min_compiles_and_verifies main ValueId(7) Stage-1パターン
22 mir_stage1_cli_emit_program_min_exec_hits_type_error main ValueId(7) Stage-1パターン
23 mir_jsonscanbox_like_seek_array_end_verifies main ValueId(2) 複雑なメソッド
24 mir_stage1_cli_entry_like_pattern_verifies main ValueId(1) return 系の型

パターン別分類

GroupA: Const命令型アテーション欠如(推定 14-16件

根本原因

src/mir/builder/emission/constant.rs で、Integer/Bool/Float/Null/Void 定数は value_types に登録されない:

// ❌ 型アノテーションなし
pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::Integer(val),
    });
    dst  // ← value_types に何も登録していない!
}

// ✅ String のみ型アノテーションあり
pub fn emit_string<S: Into<String>>(b: &mut MirBuilder, s: S) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::String(s.into()),
    });
    // 🎯 Phase 3-A: String constant type annotation
    b.value_types.insert(dst, MirType::Box("StringBox".to_string()));
    b.value_origin_newbox.insert(dst, "StringBox".to_string());
    dst
}

影響範囲

  • return 0 のような整数リテラル return
  • return true/return false のような真偽値 return
  • return 3.14 のような浮動小数点 return
  • return nullreturn void

該当テスト

  • #6: mir_locals_uninitialized (return 0)
  • #14-20: mir_stageb_like_*_verifies (全て return 系)
  • #24: mir_stage1_cli_entry_like_pattern_verifies

GroupB: Copy命令型伝播不足(推定 6-8件

根本原因

Copy 命令で値がコピーされた際、型情報が伝播しないケースがある。

src/mir/builder/metadata/propagate.rs には型伝播機能があるが、すべての Copy 命令で呼ばれるわけではない:

// Phase 3: 型伝播(一部のケースのみ)
if let Some(t) = builder.value_types.get(&src).cloned() {
    builder.value_types.insert(dst, t);
}

影響範囲

  • Loop exit 後の edge copy
  • If merge 後の edge copy
  • PHI 命令からの Copy

該当テスト

  • #3-5, #7-8, #10-12: Loop break/continue 後の edge copy
  • #9: If merge 後の edge copy
  • #11: Loop 内 If の edge copy

GroupC: PHI命令型推論不足(推定 4-6件

根本原因

GenericTypeResolver::resolve_from_phi() は以下のケースで失敗する:

  1. ret_val が PHI の出力ではない
  2. PHI の incoming 値の型が不一致
  3. incoming 値の型が value_types に未登録
pub fn resolve_from_phi(
    function: &MirFunction,
    ret_val: ValueId,
    types: &BTreeMap<ValueId, MirType>,
) -> Option<MirType> {
    for (_bid, bb) in function.blocks.iter() {
        for inst in bb.instructions.iter() {
            if let MirInstruction::Phi { dst, inputs, .. } = inst {
                if *dst == ret_val {
                    let mut it = inputs.iter().filter_map(|(_, v)| types.get(v));
                    if let Some(first) = it.next() {
                        if it.all(|mt| mt == first) {
                            return Some(first.clone());  // ← 全て同じ型の時のみ成功
                        }
                    }
                }
            }
        }
    }
    None  // ← PHI が見つからない、または型不一致
}

影響範囲

  • 複雑な制御フローAwait/Try-Catch
  • 多段 PHI チェーンPHI → Copy → PHI
  • 型が異なる incoming 値を持つ PHI

該当テスト

  • #1: test_lowering_await_expression (Await式)
  • #2: test_try_catch_compilation (Try-Catch式)
  • #13: mir_funcscanner_skip_ws_min_verify_and_vm
  • #21-22: Stage-1 CLI パターン

GroupD: その他の命令型(推定 2-4件

可能性のある原因

  • BoxCall/Call 命令の戻り値型 が未登録
  • NewBox 命令の戻り値型 が未登録(稀)
  • TypeOp 命令の戻り値型 が未登録
  • UnaryOp/BinOp 命令の戻り値型 が一部未登録

該当テスト

  • #23: mir_jsonscanbox_like_seek_array_end_verifies (複雑なメソッド)

解決策の優先順位

Phase 84-1: Const命令型アテーション追加(最優先・最大効果)

期待される効果: 14-16件のテストが修正される58-67%

実装箇所: src/mir/builder/emission/constant.rs

// ✅ 修正案
pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::Integer(val),
    });
    b.value_types.insert(dst, MirType::Integer);  // ← 追加
    dst
}

pub fn emit_bool(b: &mut MirBuilder, val: bool) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::Bool(val),
    });
    b.value_types.insert(dst, MirType::Bool);  // ← 追加
    dst
}

pub fn emit_float(b: &mut MirBuilder, val: f64) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::Float(val),
    });
    b.value_types.insert(dst, MirType::Float);  // ← 追加
    dst
}

pub fn emit_null(b: &mut MirBuilder) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::Null,
    });
    b.value_types.insert(dst, MirType::Null);  // ← 追加
    dst
}

pub fn emit_void(b: &mut MirBuilder) -> ValueId {
    let dst = b.next_value_id();
    let _ = b.emit_instruction(MirInstruction::Const {
        dst,
        value: ConstValue::Void,
    });
    b.value_types.insert(dst, MirType::Void);  // ← 追加
    dst
}

リスク: 極めて低いString は既に実装済み)


Phase 84-2: Copy命令型伝播の徹底(次点・中効果)

期待される効果: 6-8件のテストが修正される25-33%

実装箇所:

  • src/mir/builder/ssa/local.rs - Local変数のCopy
  • src/mir/builder/metadata/propagate.rs - 一般的な型伝播
  • src/mir/phi_core/loop_phi.rs - Loop exit edge copy
  • src/mir/phi_core/if_phi.rs - If merge edge copy

実装方針:

  1. すべての emit_copy() 呼び出し箇所を洗い出す
  2. 型伝播が欠けている箇所に propagate_type() を追加
  3. Edge copy 生成時に元の ValueId の型を継承
// ✅ 修正案loop_phi.rs
fn emit_edge_copy(builder: &mut MirBuilder, src: ValueId) -> ValueId {
    let dst = builder.next_value_id();
    builder.emit_instruction(MirInstruction::Copy { dst, src });

    // 型伝播を追加
    if let Some(ty) = builder.value_types.get(&src).cloned() {
        builder.value_types.insert(dst, ty);
    }

    dst
}

リスク: 中程度(既存の型伝播ロジックとの整合性確認が必要)


Phase 84-3: PHI型推論の強化(長期・小効果)

期待される効果: 4-6件のテストが修正される17-25%

実装方針:

  1. 多段PHIチェーン対応: PHI → Copy → PHI の解析
  2. 型不一致PHI対応: 共通の上位型(例: Integer | Null → Any
  3. await/try-catch専用: 特殊構文用の型ヒント

実装箇所: src/mir/join_ir/lowering/generic_type_resolver.rs

// ✅ 拡張案
pub fn resolve_from_phi_recursive(
    function: &MirFunction,
    ret_val: ValueId,
    types: &BTreeMap<ValueId, MirType>,
    depth: usize,  // 再帰深度制限
) -> Option<MirType> {
    if depth > 5 {
        return None;  // 無限ループ防止
    }

    // 1. 直接 PHI を探す
    if let Some(ty) = resolve_from_phi(function, ret_val, types) {
        return Some(ty);
    }

    // 2. Copy 経由で PHI を探す
    for (_bid, bb) in function.blocks.iter() {
        for inst in bb.instructions.iter() {
            if let MirInstruction::Copy { dst, src } = inst {
                if *dst == ret_val {
                    return resolve_from_phi_recursive(function, *src, types, depth + 1);
                }
            }
        }
    }

    None
}

リスク: 高(再帰的解析のパフォーマンスと正確性)


アクションアイテム

即座に実装すべき項目

  1. Phase 84-1 実装 (最優先)

    • constant.rs の 5 関数に型アノテーション追加
    • テスト実行して 14-16 件の修正を確認
    • 期待: Case D が 24件 → 8-10件に削減
  2. Phase 84-2 実装 (次点)

    • Copy 命令の型伝播を徹底
    • Edge copy 専用のヘルパー関数を作成
    • 期待: Case D が 8-10件 → 2-4件に削減

後回しでも良い項目

  1. Phase 84-3 検討 (長期)
    • 多段 PHI チェーンが本当に必要か検証
    • await/try-catch の型推論を専用実装で対応
    • 期待: Case D が 2-4件 → 0件完全解決

まとめ

Case D の主要原因:

  1. Const命令の型アテーション欠如 (58-67%)
  2. Copy命令の型伝播不足 (25-33%)
  3. PHI型推論の限界 (17-25%)

推奨アプローチ:

  • Phase 84-1 を即座に実装1-2時間で完了、大幅改善
  • Phase 84-2 を段階的に実装1-2日で完了、ほぼ完全解決
  • Phase 84-3 は残存ケースを見てから判断

期待される最終結果:

  • Case D: 24件 → 0-2件90-100%解決)
  • テスト成功率: 471/523 (90%) → 519-521/523 (99-100%)