diff --git a/docs/development/current/main/phase84-2-case-d-investigation.md b/docs/development/current/main/phase84-2-case-d-investigation.md new file mode 100644 index 00000000..3dc02b7a --- /dev/null +++ b/docs/development/current/main/phase84-2-case-d-investigation.md @@ -0,0 +1,434 @@ +# Phase 84-2: Case D 残り 9件の詳細調査 + +## 概要 + +Phase 84-2 で CopyTypePropagator を実装した結果、Case D は 12件 → 9件に削減されました。 +本ドキュメントは残り 9件の詳細分析結果をまとめます。 + +## 削減された 3件(Phase 84-2 で解決) + +CopyTypePropagator により以下のパターンが解決されました: +- **Copy チェーン伝播**: `r1 = Copy r0` → `r2 = PHI [r1, r3]` で r0 の型が r2 に伝播 +- **多段 Copy 追跡**: Copy 命令を遡って元の ValueId の型を発見 + +## 残り 9件の一覧 + +| # | テスト名 | ValueId | パターン分類 | +|---|---------|---------|------------| +| 1 | `test_lowering_await_expression` | ValueId(2) | GroupC: await 特殊パターン | +| 2 | `loop_with_continue_and_break_edge_copy_merge` | ValueId(56) | GroupA: Loop + continue/break PHI | +| 3 | `nested_loop_with_multi_continue_break_edge_copy_merge` | ValueId(135) | GroupA: Nested loop 複雑 PHI | +| 4 | `loop_inner_if_multilevel_edge_copy` | ValueId(74) | GroupA: Loop + 多段 if | +| 5 | `loop_break_and_early_return_edge_copy` | ValueId(40) | GroupA: Loop + early return | +| 6 | `vm_exec_break_inside_if` | ValueId(27) | GroupA: Loop + if-break | +| 7 | `loop_if_three_level_merge_edge_copy` | ValueId(75) | GroupA: Loop + 3段 if | +| 8 | `mir_stage1_cli_emit_program_min_exec_hits_type_error` | ValueId(7) | GroupB: Stage1Cli 複雑型推論 | +| 9 | `mir_stage1_cli_emit_program_min_compiles_and_verifies` | ValueId(7) | GroupB: Stage1Cli 複雑型推論 | + +## パターン分類の詳細 + +### GroupA: Loop 制御フロー PHI(7件) + +**共通特徴**: +- `NYASH_MIR_NO_PHI=1` でテスト(PHI-off モード) +- Loop + continue/break による複雑な制御フロー +- Edge Copy が複数の経路から合流する PHI + +**典型的な制御フロー**: +``` +loop(condition) { + if (cond1) { break } // → after_loop へ edge copy + if (cond2) { continue } // → loop_header へ edge copy + normal_path // → loop_header へ edge copy +} +return merged_value // ← PHI の型が未解決 +``` + +**問題の本質**: +- PHI の incoming 値が全て Edge Copy の dst ValueId +- Edge Copy の src ValueId は value_types に登録されている +- しかし、GenericTypeResolver は **PHI の incoming 値の型** しか見ない +- **Copy の src を遡る処理が不足** + +**なぜ CopyTypePropagator で解決できなかったか**: +```rust +// CopyTypePropagator の現在のロジック +if let Some(ty) = types.get(&src) { + types.insert(dst, ty.clone()); // ← dst に型を登録 +} +``` + +問題点: +- PHI の incoming 値 (dst) に型を登録 +- しかし、GenericTypeResolver::resolve_from_phi() は **既に登録された型** を参照 +- **参照のタイミングが遅い**: lifecycle.rs が return 型を要求する時点で、 + CopyTypePropagator はまだ実行されていない + +**具体例: loop_with_continue_and_break_edge_copy_merge** + +```hako +// 簡略化したコード +i = 0 +sum = 0 +loop(i < 5) { + i = i + 1 + if (i == 3) { break } // → edge copy: sum_final = sum + if (i % 2 == 0) { continue } // → edge copy: sum_loop = sum + sum = sum + i +} +return sum // ← ValueId(56) の型が未解決 +``` + +MIR 構造(推測): +``` +Block1 (loop_header): + %sum_header = PHI [%sum_init, %sum_loop, %sum_updated] + +Block2 (break): + %sum_final = Copy %sum_header ← value_types に型登録済み + Jump after_loop + +Block3 (continue): + %sum_loop = Copy %sum_header ← value_types に型登録済み + Jump loop_header + +Block4 (after_loop): + %56 = PHI [%sum_final] ← incoming の型が未登録! + Return %56 +``` + +**テストファイルの所在**: +- `src/tests/loop_continue_break_no_phi_tests.rs` +- `src/tests/loop_nested_no_phi_tests.rs` +- `src/tests/loop_return_no_phi_tests.rs` +- `src/tests/mir_ctrlflow_break_continue.rs` + +### GroupB: Stage1Cli 複雑型推論(2件) + +**共通特徴**: +- `mir_stage1_cli_emit_program_min.rs` の 2テスト +- static box + env.get/set による複雑な型フロー +- ValueId(7) が Main.main の戻り値 + +**コードの特徴**: +```hako +static box Stage1Cli { + emit_program_json(source) { + if source == null || source == "" { return null } + return "{prog:" + source + "}" + } + + stage1_main(args) { + local src = env.get("STAGE1_SOURCE") + if src == null || src == "" { return 96 } + local prog = me.emit_program_json(src) + if prog == null { return 96 } + print(prog) + return 0 + } +} + +static box Main { + main(args) { + env.set("STAGE1_SOURCE", "apps/tests/stage1_using_minimal.hako") + return Stage1Cli.stage1_main(args) // ← ValueId(7) の型 + } +} +``` + +**問題の本質**: +- 多段メソッド呼び出し: `Main.main` → `Stage1Cli.stage1_main` → `emit_program_json` +- 複数の return 経路: null / 96 / 0 +- PHI が複数の経路から合流 + +**デバッグ情報**: +``` +[DEBUG/build_block] Completed, returning value ValueId(14) +[DEBUG/build_block] Completed, returning value ValueId(83) +[DEBUG/build_block] Completed, returning value ValueId(95) +[DEBUG/build_block] Completed, returning value ValueId(47) +[DEBUG/build_block] Completed, returning value ValueId(63) +[DEBUG/build_block] Completed, returning value ValueId(7) +``` + +多数の ValueId が生成されており、PHI 合流が複雑であることを示唆。 + +**テストファイル**: +- `src/tests/mir_stage1_cli_emit_program_min.rs` + +### GroupC: await 特殊パターン(1件) + +**テスト**: `test_lowering_await_expression` +**ValueId**: ValueId(2) + +**コードの特徴**: +```rust +// src/mir/mod.rs:363 +let ast = ASTNode::AwaitExpression { + expression: Box::new(ASTNode::Literal { + value: LiteralValue::Integer(1), + span: crate::ast::Span::unknown(), + }), + span: crate::ast::Span::unknown(), +}; +``` + +**問題の本質**: +- await 式の MIR lowering が特殊な制御フローを生成 +- Core-13 pure mode では skip される(非同期システム未実装) +- ValueId(2) は await の戻り値 + +**なぜ特殊か**: +- await は将来的に Safepoint/Checkpoint 命令に変換される予定 +- 現在は簡易実装のため、型推論が不完全 + +**テストファイル**: +- `src/mir/mod.rs:363-384` + +## Phase 84-3 で必要な機能の推奨 + +### 推奨1: Edge Copy 追跡 PHI 型推論(優先度: 高) + +**対象**: GroupA(7件) + +**アルゴリズム**: +```rust +// GenericTypeResolver に追加 +pub fn resolve_from_phi_with_copy_trace( + function: &MirFunction, + ret_val: ValueId, + types: &BTreeMap, +) -> Option { + // 1. PHI 命令を探索 + for inst in find_phi_instructions(function, ret_val) { + if let MirInstruction::Phi { inputs, .. } = inst { + // 2. incoming 値ごとに Copy を遡る + let mut inferred_types = Vec::new(); + for (_, incoming_val) in inputs { + // 2-1. incoming_val の型を直接取得 + if let Some(ty) = types.get(incoming_val) { + inferred_types.push(ty.clone()); + continue; + } + + // 2-2. incoming_val を定義する Copy 命令を探索 + if let Some(src_val) = find_copy_src(function, *incoming_val) { + if let Some(ty) = types.get(&src_val) { + inferred_types.push(ty.clone()); + continue; + } + } + + // 2-3. 多段 Copy を再帰的に遡る + if let Some(ty) = trace_copy_chain(function, *incoming_val, types, 10) { + inferred_types.push(ty); + } + } + + // 3. 全ての型が一致すれば返す + if let Some(first) = inferred_types.first() { + if inferred_types.iter().all(|t| t == first) { + return Some(first.clone()); + } + } + } + } + None +} + +fn trace_copy_chain( + function: &MirFunction, + start: ValueId, + types: &BTreeMap, + max_depth: usize, +) -> Option { + let mut current = start; + for _ in 0..max_depth { + if let Some(ty) = types.get(¤t) { + return Some(ty.clone()); + } + if let Some(src) = find_copy_src(function, current) { + current = src; + } else { + break; + } + } + None +} +``` + +**実装箇所**: +- `src/mir/join_ir/lowering/generic_type_resolver.rs` + +**期待効果**: +- GroupA の 7件を一気に解決 +- Loop + continue/break パターンの完全対応 + +### 推奨2: 多段 PHI 型推論(優先度: 中) + +**対象**: GroupB(2件) + +**問題**: +``` +Block1: + %a = PHI [const_96, const_0] + +Block2: + %b = PHI [%a, const_0] + +Block3: + %7 = PHI [%b] ← %b の型が未解決 +``` + +**アルゴリズム**: +```rust +pub fn resolve_from_phi_recursive( + function: &MirFunction, + ret_val: ValueId, + types: &BTreeMap, + visited: &mut HashSet, +) -> Option { + if visited.contains(&ret_val) { + return None; // 循環検出 + } + visited.insert(ret_val); + + // 1. 直接型推論を試みる + if let Some(ty) = resolve_from_phi(function, ret_val, types) { + return Some(ty); + } + + // 2. PHI の incoming 値を再帰的に解決 + for inst in find_phi_instructions(function, ret_val) { + if let MirInstruction::Phi { inputs, .. } = inst { + let mut inferred_types = Vec::new(); + for (_, incoming_val) in inputs { + // 再帰的に型を解決 + if let Some(ty) = resolve_from_phi_recursive( + function, *incoming_val, types, visited + ) { + inferred_types.push(ty); + } + } + + if let Some(first) = inferred_types.first() { + if inferred_types.iter().all(|t| t == first) { + return Some(first.clone()); + } + } + } + } + None +} +``` + +**実装箇所**: +- `src/mir/join_ir/lowering/generic_type_resolver.rs` + +**期待効果**: +- GroupB の 2件を解決 +- 多段メソッド呼び出しの型推論強化 + +### 推奨3: await 型推論特殊処理(優先度: 低) + +**対象**: GroupC(1件) + +**短期対応**: +```rust +// lifecycle.rs に特殊ケース追加 +if function_name == "main" && is_await_expression { + // await の戻り値型は Unknown で許容 + return MirType::Unknown; +} +``` + +**長期対応**: +- Phase 67+ で async/await システム完全実装 +- Safepoint/Checkpoint 命令の型推論統合 + +**実装箇所**: +- `src/mir/builder/lifecycle.rs` + +**期待効果**: +- GroupC の 1件を解決(暫定) + +## 推奨実装順序 + +### Phase 84-3: Edge Copy 追跡 PHI 型推論(1-2日) + +**目標**: GroupA の 7件を解決 + +**ステップ**: +1. `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装 +2. `trace_copy_chain()` ヘルパー関数実装 +3. `find_copy_src()` ヘルパー関数実装 +4. lifecycle.rs から新関数を呼び出す +5. テスト実行: 7件 → 0件 を確認 + +### Phase 84-4: 多段 PHI 型推論(1-2日) + +**目標**: GroupB の 2件を解決 + +**ステップ**: +1. `GenericTypeResolver::resolve_from_phi_recursive()` 実装 +2. 循環検出ロジック実装 +3. lifecycle.rs から新関数を呼び出す +4. テスト実行: 2件 → 0件 を確認 + +### Phase 84-5: await 暫定対応(30分) + +**目標**: GroupC の 1件を解決(暫定) + +**ステップ**: +1. lifecycle.rs に await 特殊ケース追加 +2. テスト実行: 1件 → 0件 を確認 + +## 完了条件 + +```bash +# Phase 84-3 完了 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 2 (GroupB のみ残存) + +# Phase 84-4 完了 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 1 (GroupC のみ残存) + +# Phase 84-5 完了 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 0 (全件解決) +``` + +## ChatGPT Pro との設計相談ポイント + +### 相談1: Edge Copy 追跡の最適化 + +**質問**: +- Copy チェーンの追跡深度は 10 で十分か? +- 循環 Copy 検出は必要か?(理論上は発生しないが) +- パフォーマンス最適化(キャッシュ戦略) + +### 相談2: 多段 PHI の循環検出 + +**質問**: +- 循環 PHI は実際に発生するか? +- 発生する場合、どう処理すべきか?(エラー or Unknown) +- visited セットの最適なデータ構造 + +### 相談3: await 型推論の長期戦略 + +**質問**: +- Phase 67+ async/await システムの型推論設計 +- Safepoint/Checkpoint 命令の型情報統合方法 +- 現在の暫定対応が将来の実装を妨げないか + +## まとめ + +Phase 84-2 の CopyTypePropagator により 12件 → 9件に削減成功。 +残り 9件は以下の 3パターンに分類: + +- **GroupA**: Loop 制御フロー PHI(7件)→ Edge Copy 追跡で解決可能 +- **GroupB**: 多段 PHI(2件)→ 再帰的型推論で解決可能 +- **GroupC**: await 特殊(1件)→ 暫定対応で解決可能 + +Phase 84-3/4/5 の実装により、**Case D を完全解決** できる見込み。 diff --git a/docs/development/current/main/phase84-2-failure-patterns.md b/docs/development/current/main/phase84-2-failure-patterns.md new file mode 100644 index 00000000..e5918863 --- /dev/null +++ b/docs/development/current/main/phase84-2-failure-patterns.md @@ -0,0 +1,390 @@ +# Phase 84-2: Case D 失敗パターン詳細 + +## GroupA: Loop 制御フロー PHI(7件) + +### パターン A-1: continue + break + +**テスト**: `loop_with_continue_and_break_edge_copy_merge` +**ValueId**: 56 + +**コード構造**: +```hako +i = 0 +sum = 0 +loop(i < 5) { + i = i + 1 + if (i == 3) { break } // ← break 経路 + if (i % 2 == 0) { continue } // ← continue 経路 + sum = sum + i // ← normal 経路 +} +return sum // ← ValueId(56) の型が未解決 +``` + +**MIR 構造(推測)**: +``` +Block_LoopHeader: + %sum_phi = PHI [%sum_init, %sum_continue, %sum_normal] + %i_phi = PHI [%i_init, %i_continue, %i_normal] + ... + +Block_Break: + %sum_break = Copy %sum_phi ← value_types に型登録済み + Jump after_loop + +Block_Continue: + %sum_continue = Copy %sum_phi ← value_types に型登録済み + Jump loop_header + +Block_Normal: + %sum_normal = BinOp Add %sum_phi %i_phi + Jump loop_header + +Block_AfterLoop: + %56 = PHI [%sum_break] ← incoming の型が未登録! + Return %56 +``` + +**問題の本質**: +- PHI(56) の incoming 値は `%sum_break` +- `%sum_break` は Copy の dst で、value_types に未登録 +- Copy の src `%sum_phi` は型登録済みだが、GenericTypeResolver は追跡しない + +**解決策**: +```rust +// GenericTypeResolver::resolve_from_phi_with_copy_trace() +for (_, incoming_val) in phi_inputs { + // Copy を遡る + if let Some(src) = find_copy_src(function, incoming_val) { + if let Some(ty) = types.get(&src) { + return Some(ty.clone()); + } + } +} +``` + +### パターン A-2: 多段 continue/break + +**テスト**: `nested_loop_with_multi_continue_break_edge_copy_merge` +**ValueId**: 135 + +**コード構造**: +```hako +i = 0 +sum = 0 +loop(i < 10) { + i = i + 1 + if (i == 2 || i == 4) { continue } // ← continue 経路1 + if (i == 7) { + if (1 == 1) { break } // ← break 経路(ネスト) + } + if ((i % 3) == 0) { continue } // ← continue 経路2 + sum = sum + i // ← normal 経路 +} +return sum // ← ValueId(135) +``` + +**特徴**: +- 複数の continue 経路 +- ネストした if 内の break +- PHI の incoming 値が多い(4-5個) + +### パターン A-3: Loop + 多段 if + +**テスト**: `loop_inner_if_multilevel_edge_copy` +**ValueId**: 74 + +**コード構造**: +```hako +j = 0 +acc = 0 +loop(j < 6) { + j = j + 1 + if (j < 3) { + if (j % 2 == 0) { continue } // ← 2段 if + continue + acc = acc + 10 + } else { + if (j == 5) { break } // ← 2段 if + break + acc = acc + 1 + } +} +return acc // ← ValueId(74) +``` + +**特徴**: +- then/else の両方に制御フロー +- 多段ネスト if +- 変数更新が複数経路に分散 + +### パターン A-4: Loop + early return + +**テスト**: `loop_break_and_early_return_edge_copy` +**ValueId**: 40 + +**コード構造**: +```hako +i = 0 +acc = 0 +loop(i < 6) { + i = i + 1 + if (i == 5) { break } // ← break 経路 + if (i == 3) { return acc } // ← early return 経路 + acc = acc + i +} +return acc // ← ValueId(40) +``` + +**特徴**: +- break と early return の混在 +- 関数終了が複数経路 +- return 型推論が複雑 + +### パターン A-5: 単純 if-break + +**テスト**: `vm_exec_break_inside_if` +**ValueId**: 27 + +**コード構造**: +```hako +local i = 0 +loop(i < 10) { + if (i == 3) { break } // ← if 内 break + i = i + 1 +} +return i // ← ValueId(27) +``` + +**特徴**: +- 最もシンプルな if-break パターン +- これが解決できればベースケース成功 + +### パターン A-6: 3段ネスト if + +**テスト**: `loop_if_three_level_merge_edge_copy` +**ValueId**: 75 + +**コード構造**: +```hako +x = 0 +i = 0 +loop(i < 7) { + i = i + 1 + if (i % 2 == 0) { + if (i == 4) { continue } // ← 3段目 continue + x = x + 2 + } else { + if (i == 5) { break } // ← 3段目 break + x = x + 1 + } +} +return x // ← ValueId(75) +``` + +**特徴**: +- 3段ネスト制御フロー +- then/else の両方に制御フロー +- 変数更新の分岐が複雑 + +## GroupB: 多段 PHI 型推論(2件) + +### パターン B-1: static box + 複数 return + +**テスト**: `mir_stage1_cli_emit_program_min_*` +**ValueId**: 7 + +**コード構造**: +```hako +static box Stage1Cli { + emit_program_json(source) { + if source == null || source == "" { return null } // ← return 経路1 + return "{prog:" + source + "}" // ← return 経路2 + } + + stage1_main(args) { + if args == null { args = new ArrayBox() } + local src = env.get("STAGE1_SOURCE") + if src == null || src == "" { return 96 } // ← return 経路3 + + local prog = me.emit_program_json(src) + if prog == null { return 96 } // ← return 経路4 + print(prog) + return 0 // ← return 経路5 + } +} + +static box Main { + main(args) { + env.set("STAGE1_SOURCE", "apps/tests/stage1_using_minimal.hako") + return Stage1Cli.stage1_main(args) // ← ValueId(7) + } +} +``` + +**MIR 構造(推測)**: +``` +Function: Stage1Cli.emit_program_json + Block1: + %1 = PHI [null, string_concat_result] + Return %1 + +Function: Stage1Cli.stage1_main + Block1: + %2 = Call Stage1Cli.emit_program_json + Block2: + %3 = PHI [%2, const_96, const_0] + Return %3 + +Function: Main.main + Block1: + %4 = Call Stage1Cli.stage1_main + Block2: + %7 = PHI [%4] ← %4 の型が未解決(多段 PHI) + Return %7 +``` + +**問題の本質**: +- PHI(7) の incoming 値は PHI(3) の結果 +- PHI(3) の incoming 値は PHI(1) の結果 +- **3段 PHI チェーン** が発生 + +**解決策**: +```rust +// GenericTypeResolver::resolve_from_phi_recursive() +pub fn resolve_from_phi_recursive( + function: &MirFunction, + ret_val: ValueId, + types: &BTreeMap, + visited: &mut HashSet, +) -> Option { + if visited.contains(&ret_val) { + return None; // 循環検出 + } + visited.insert(ret_val); + + // PHI の incoming 値を再帰的に解決 + for (_, incoming_val) in phi_inputs { + if let Some(ty) = resolve_from_phi_recursive( + function, *incoming_val, types, visited + ) { + return Some(ty); + } + } + None +} +``` + +## GroupC: await 特殊パターン(1件) + +### パターン C-1: await 式 + +**テスト**: `test_lowering_await_expression` +**ValueId**: 2 + +**コード構造**: +```rust +// Rust AST 生成 +let ast = ASTNode::AwaitExpression { + expression: Box::new(ASTNode::Literal { + value: LiteralValue::Integer(1), + span: crate::ast::Span::unknown(), + }), + span: crate::ast::Span::unknown(), +}; +``` + +**MIR 構造(推測)**: +``` +Block1: + %1 = Const Integer(1) + %2 = Await %1 ← await 命令の戻り値 + Return %2 +``` + +**問題の本質**: +- await 式の型推論が未実装 +- 非同期システム(Safepoint/Checkpoint)が Phase 67+ 実装予定 +- 現在は MIR13 migration pending + +**暫定対応**: +```rust +// lifecycle.rs に特殊ケース追加 +if is_await_expression { + // await の戻り値型は Unknown で許容 + return MirType::Unknown; +} +``` + +**長期対応(Phase 67+)**: +- async/await システム完全実装 +- type_hint による await 型推論 +- Safepoint/Checkpoint 命令統合 + +## 解決優先度 + +### 優先度1: GroupA(7件) + +**理由**: +- 最も頻出するパターン +- Loop 制御フローは実用コードで必須 +- Edge Copy 追跡で一気に解決可能 + +**期待効果**: 9件 → 2件(78%削減) + +### 優先度2: GroupB(2件) + +**理由**: +- static box は Stage1Cli で使用中 +- 多段メソッド呼び出しも実用的 +- 再帰的 PHI 推論で解決可能 + +**期待効果**: 2件 → 1件(50%削減) + +### 優先度3: GroupC(1件) + +**理由**: +- await は実験的機能 +- 本格実装は Phase 67+ 予定 +- 暫定対応で十分 + +**期待効果**: 1件 → 0件(100%削減) + +## 実装チェックリスト + +### Phase 84-3: Edge Copy 追跡 + +- [ ] `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装 +- [ ] `find_copy_src()` ヘルパー関数実装 +- [ ] `trace_copy_chain()` ヘルパー関数実装 +- [ ] lifecycle.rs 統合 +- [ ] テスト実行: GroupA の 7件を確認 + +### Phase 84-4: 多段 PHI 推論 + +- [ ] `GenericTypeResolver::resolve_from_phi_recursive()` 実装 +- [ ] 循環検出ロジック実装 +- [ ] lifecycle.rs 統合 +- [ ] テスト実行: GroupB の 2件を確認 + +### Phase 84-5: await 暫定対応 + +- [ ] lifecycle.rs に await 特殊ケース追加 +- [ ] テスト実行: GroupC の 1件を確認 + +## 完了確認 + +```bash +# Phase 84-3 完了 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 2 + +# Phase 84-4 完了 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 1 + +# Phase 84-5 完了 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" +# 期待: 出力なし(0件) + +# 最終確認 +cargo test --release --lib +# 期待: test result: ok +``` diff --git a/docs/development/current/main/phase84-2-summary.md b/docs/development/current/main/phase84-2-summary.md new file mode 100644 index 00000000..9c36a103 --- /dev/null +++ b/docs/development/current/main/phase84-2-summary.md @@ -0,0 +1,211 @@ +# Phase 84-2: CopyTypePropagator 実装完了サマリー + +## 成果 + +### 削減結果 + +``` +Before Phase 84-2: 12件の Case D 失敗 +After Phase 84-2: 9件の Case D 失敗 + +削減数: 3件 (25%削減) +``` + +### 実装内容 + +**新規作成ファイル**: +- `src/mir/phi_core/copy_type_propagator.rs` (125行) + +**主要機能**: +```rust +pub struct CopyTypePropagator; + +impl CopyTypePropagator { + pub fn propagate( + function: &MirFunction, + types: &mut BTreeMap, + ) { + // Copy 命令を走査して型を伝播 + for inst in all_copy_instructions(function) { + if let Some(src_type) = types.get(&src) { + types.insert(dst, src_type.clone()); + } + } + } +} +``` + +**統合箇所**: +- `src/mir/builder/lifecycle.rs:371` - infer_type_from_phi() の直前に呼び出し + +## 残り 9件の分類 + +### GroupA: Loop 制御フロー PHI(7件) + +**パターン**: Loop + continue/break による Edge Copy 合流 + +**典型的なコード**: +```hako +i = 0 +sum = 0 +loop(i < 5) { + i = i + 1 + if (i == 3) { break } // → edge copy + if (i % 2 == 0) { continue } // → edge copy + sum = sum + i +} +return sum // ← PHI の型が未解決 +``` + +**問題**: PHI の incoming 値が Edge Copy の dst で、src の型を遡れない + +**テスト一覧**: +1. `loop_with_continue_and_break_edge_copy_merge` - ValueId(56) +2. `nested_loop_with_multi_continue_break_edge_copy_merge` - ValueId(135) +3. `loop_inner_if_multilevel_edge_copy` - ValueId(74) +4. `loop_break_and_early_return_edge_copy` - ValueId(40) +5. `vm_exec_break_inside_if` - ValueId(27) +6. `loop_if_three_level_merge_edge_copy` - ValueId(75) +7. (GroupA 合計 7件) + +### GroupB: 多段 PHI 型推論(2件) + +**パターン**: 複数の PHI 命令が連鎖 + +**典型的なコード**: +```hako +static box Stage1Cli { + stage1_main(args) { + if cond1 { return 96 } + if cond2 { return 96 } + return 0 + } +} + +static box Main { + main(args) { + return Stage1Cli.stage1_main(args) // ← 多段 PHI + } +} +``` + +**問題**: PHI の incoming 値が別の PHI で、再帰的に解決できない + +**テスト一覧**: +1. `mir_stage1_cli_emit_program_min_exec_hits_type_error` - ValueId(7) +2. `mir_stage1_cli_emit_program_min_compiles_and_verifies` - ValueId(7) + +### GroupC: await 特殊パターン(1件) + +**パターン**: await 式の MIR lowering + +**コード**: +```rust +let ast = ASTNode::AwaitExpression { + expression: Box::new(ASTNode::Literal { + value: LiteralValue::Integer(1), + ... + }), + ... +}; +``` + +**問題**: await の型推論が未実装(非同期システム未完成) + +**テスト**: +1. `test_lowering_await_expression` - ValueId(2) + +## Phase 84-3 実装推奨 + +### 目標: GroupA の 7件を解決 + +**新機能**: Edge Copy 追跡 PHI 型推論 + +**実装方針**: +```rust +// GenericTypeResolver に追加 +pub fn resolve_from_phi_with_copy_trace( + function: &MirFunction, + ret_val: ValueId, + types: &BTreeMap, +) -> Option { + // PHI の incoming 値から Copy を遡る + for (_, incoming_val) in phi_inputs { + // 1. 直接型取得を試みる + if let Some(ty) = types.get(incoming_val) { + continue; + } + + // 2. Copy 命令を遡る + if let Some(src) = find_copy_src(function, incoming_val) { + if let Some(ty) = types.get(&src) { + // src の型を使用 + } + } + + // 3. 多段 Copy を再帰的に追跡 + if let Some(ty) = trace_copy_chain(function, incoming_val, types) { + // チェーンを遡った型を使用 + } + } +} +``` + +**期待効果**: +- 9件 → 2件に削減(GroupB + GroupC のみ残存) +- Loop 制御フローの型推論が完全動作 + +### 実装ファイル + +- `src/mir/join_ir/lowering/generic_type_resolver.rs` - 新関数追加 +- `src/mir/builder/lifecycle.rs` - 新関数呼び出し統合 + +### テスト検証 + +```bash +# Phase 84-3 完了確認 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 2 (GroupB のみ) +``` + +## Phase 84-4/5 展望 + +### Phase 84-4: 多段 PHI 型推論 + +**目標**: GroupB の 2件を解決 + +**実装**: `resolve_from_phi_recursive()` で PHI チェーンを再帰的に追跡 + +### Phase 84-5: await 暫定対応 + +**目標**: GroupC の 1件を解決 + +**実装**: lifecycle.rs に await 特殊ケース追加(暫定) + +## 完了条件 + +```bash +# 全 Case D 解決 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" +# 期待: 出力なし(0件) + +# 最終確認 +cargo test --release --lib +# 期待: test result: ok +``` + +## タイムライン + +- **Phase 84-2**: 完了 ✅ (12件 → 9件) +- **Phase 84-3**: 推定 1-2日 (9件 → 2件) +- **Phase 84-4**: 推定 1-2日 (2件 → 1件) +- **Phase 84-5**: 推定 30分 (1件 → 0件) + +**合計**: 2-4日で Case D 完全解決見込み + +## 参考資料 + +- [Phase 84-2 詳細調査](./phase84-2-case-d-investigation.md) +- [CopyTypePropagator 実装](../../../src/mir/phi_core/copy_type_propagator.rs) +- [GenericTypeResolver](../../../src/mir/join_ir/lowering/generic_type_resolver.rs) +- [lifecycle.rs 統合箇所](../../../src/mir/builder/lifecycle.rs:371) diff --git a/docs/development/current/main/phase84-2-test-list.md b/docs/development/current/main/phase84-2-test-list.md new file mode 100644 index 00000000..f9715458 --- /dev/null +++ b/docs/development/current/main/phase84-2-test-list.md @@ -0,0 +1,120 @@ +# Phase 84-2: Case D 残り 9件クイックリファレンス + +## 一覧表 + +| # | Group | テスト名 | ValueId | ファイル | 行番号 | +|---|-------|---------|---------|---------|-------| +| 1 | C | `test_lowering_await_expression` | 2 | `src/mir/mod.rs` | 363 | +| 2 | A | `loop_with_continue_and_break_edge_copy_merge` | 56 | `src/tests/loop_continue_break_no_phi_tests.rs` | 21 | +| 3 | A | `nested_loop_with_multi_continue_break_edge_copy_merge` | 135 | `src/tests/loop_nested_no_phi_tests.rs` | 21 | +| 4 | A | `loop_inner_if_multilevel_edge_copy` | 74 | `src/tests/loop_nested_no_phi_tests.rs` | 224 | +| 5 | A | `loop_break_and_early_return_edge_copy` | 40 | `src/tests/loop_return_no_phi_tests.rs` | 22 | +| 6 | A | `vm_exec_break_inside_if` | 27 | `src/tests/mir_ctrlflow_break_continue.rs` | 47 | +| 7 | A | `loop_if_three_level_merge_edge_copy` | 75 | `src/tests/loop_return_no_phi_tests.rs` | 194 | +| 8 | B | `mir_stage1_cli_emit_program_min_exec_hits_type_error` | 7 | `src/tests/mir_stage1_cli_emit_program_min.rs` | 97 | +| 9 | B | `mir_stage1_cli_emit_program_min_compiles_and_verifies` | 7 | `src/tests/mir_stage1_cli_emit_program_min.rs` | 71 | + +## グループ詳細 + +### GroupA: Loop 制御フロー PHI(7件) + +**共通パターン**: Loop + continue/break + +**テスト実行**: +```bash +# 個別テスト +cargo test --release --lib loop_with_continue_and_break_edge_copy_merge + +# GroupA 全体 +cargo test --release --lib loop_continue_break +cargo test --release --lib loop_nested +cargo test --release --lib loop_return +cargo test --release --lib vm_exec_break +``` + +**期待される解決策**: Edge Copy 追跡 PHI 型推論 + +### GroupB: 多段 PHI 型推論(2件) + +**共通パターン**: static box + 複数 return 経路 + +**テスト実行**: +```bash +# GroupB 全体 +cargo test --release --lib mir_stage1_cli_emit_program_min +``` + +**期待される解決策**: 再帰的 PHI 型推論 + +### GroupC: await 特殊パターン(1件) + +**パターン**: await 式の MIR lowering + +**テスト実行**: +```bash +cargo test --release --lib test_lowering_await_expression +``` + +**期待される解決策**: await 特殊ケース処理(暫定) + +## 実行コマンド集 + +### 全 Case D 確認 + +```bash +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep -B5 "Case D" +``` + +### ValueId 一覧取得 + +```bash +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "ValueId:" | sort | uniq +``` + +### グループ別実行 + +```bash +# GroupA のみ +cargo test --release --lib loop_ mir_ctrlflow_break + +# GroupB のみ +cargo test --release --lib mir_stage1_cli + +# GroupC のみ +cargo test --release --lib test_lowering_await +``` + +## デバッグ用環境変数 + +```bash +# MIR ダンプ +NYASH_DUMP_MIR=1 cargo test --release --lib + +# 詳細ログ +RUST_LOG=debug cargo test --release --lib + +# バックトレース +RUST_BACKTRACE=1 cargo test --release --lib +``` + +## 次のステップ + +1. **Phase 84-3**: GroupA の 7件を解決 + - `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装 + - Edge Copy 追跡ロジック追加 + - 期待: 9件 → 2件 + +2. **Phase 84-4**: GroupB の 2件を解決 + - `GenericTypeResolver::resolve_from_phi_recursive()` 実装 + - 再帰的 PHI 型推論 + - 期待: 2件 → 1件 + +3. **Phase 84-5**: GroupC の 1件を解決 + - await 特殊ケース追加 + - 期待: 1件 → 0件 + +## 参考資料 + +- [詳細調査](./phase84-2-case-d-investigation.md) +- [サマリー](./phase84-2-summary.md) +- [CopyTypePropagator 実装](../../../src/mir/phi_core/copy_type_propagator.rs) diff --git a/docs/development/current/main/phase84-case-d-detailed-analysis.md b/docs/development/current/main/phase84-case-d-detailed-analysis.md index 026cd544..c93c1136 100644 --- a/docs/development/current/main/phase84-case-d-detailed-analysis.md +++ b/docs/development/current/main/phase84-case-d-detailed-analysis.md @@ -2,10 +2,14 @@ ## 概要 -Phase 83 で Case D が 20件 → **24件** に増加(調査時点)。 -本レポートでは全 24 件の Case D 失敗を詳細に分析し、不足している型推論パターンを特定する。 +Phase 83 で Case D が 20 件 → **15 件** に減少(MethodReturnHintBox 実装)。 +その後 Phase 84-1(Const 命令型アノテーション追加)で **12 件**、Phase 84-2(CopyTypePropagator 導入)で **9 件** まで削減された。 -**重要な発見**: 主要な原因は **Const命令の型アノテーション欠如** である。 +本レポート自体は「24 件あった調査時点」の分析ログとして残しつつ、 +現在は Const 欠如グループと単純な Copy チェーンは解消され、残りは主に PHI を含む複雑なパターンであることが判明している。 + +**重要な発見(当時)**: 主要な原因は **Const命令の型アノテーション欠如** である。 +**補足(現在)**: Const 命令については 40dfbc68 で修正済み、Copy 伝播については CopyTypePropagator(Phase 84-2)で整理済み。 --- @@ -15,7 +19,7 @@ Phase 83 で Case D が 20件 → **24件** に増加(調査時点)。 NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 ``` -**テスト結果**: 471 passed; **52 failed** (うち Case D は24件) +**テスト結果(当時)**: 471 passed; **52 failed** (うち Case D は24件) --- diff --git a/docs/development/current/main/phase84-case-d-index.md b/docs/development/current/main/phase84-case-d-index.md new file mode 100644 index 00000000..dc79faff --- /dev/null +++ b/docs/development/current/main/phase84-case-d-index.md @@ -0,0 +1,237 @@ +# Phase 84: Case D 完全解決ロードマップ + +## 現在の状況 + +``` +Phase 84-2 完了: 12件 → 9件(25%削減) +残り: 9件 + +内訳: +- GroupA (Loop 制御フロー): 7件 +- GroupB (多段 PHI): 2件 +- GroupC (await 特殊): 1件 +``` + +## ドキュメント一覧 + +### 📊 サマリー + +- **[Phase 84-2 サマリー](./phase84-2-summary.md)** - 実装完了報告と次のステップ +- **[Phase 84-2 テスト一覧](./phase84-2-test-list.md)** - クイックリファレンス表 + +### 📖 詳細分析 + +- **[Phase 84-2 詳細調査](./phase84-2-case-d-investigation.md)** - 9件の分類と解決策提案 +- **[Phase 84-2 失敗パターン](./phase84-2-failure-patterns.md)** - 各パターンのコード例と MIR 構造 + +### 🔧 実装資料 + +- **[CopyTypePropagator 実装](../../../src/mir/phi_core/copy_type_propagator.rs)** - Phase 84-2 で実装 +- **[GenericTypeResolver](../../../src/mir/join_ir/lowering/generic_type_resolver.rs)** - Phase 84-3/4 で拡張予定 +- **[lifecycle.rs](../../../src/mir/builder/lifecycle.rs)** - 型推論統合箇所 + +## クイックリンク + +### 🎯 次のタスク + +**Phase 84-3: Edge Copy 追跡 PHI 型推論** +- 目標: GroupA の 7件を解決 +- 期待: 9件 → 2件(78%削減) +- 期間: 1-2日 + +**実装内容**: +```rust +// GenericTypeResolver に追加 +pub fn resolve_from_phi_with_copy_trace( + function: &MirFunction, + ret_val: ValueId, + types: &BTreeMap, +) -> Option { + // PHI の incoming 値から Copy を遡る + for (_, incoming_val) in phi_inputs { + if let Some(src) = find_copy_src(function, incoming_val) { + if let Some(ty) = types.get(&src) { + return Some(ty.clone()); + } + } + } + None +} +``` + +### 🧪 テスト実行 + +```bash +# 全 Case D 確認 +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" + +# GroupA のみ +cargo test --release --lib loop_continue_break +cargo test --release --lib loop_nested +cargo test --release --lib loop_return +cargo test --release --lib vm_exec_break + +# GroupB のみ +cargo test --release --lib mir_stage1_cli + +# GroupC のみ +cargo test --release --lib test_lowering_await +``` + +## 完了条件 + +### Phase 84-3 完了 + +```bash +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 2 (GroupB のみ残存) +``` + +### Phase 84-4 完了 + +```bash +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" | wc -l +# 期待: 1 (GroupC のみ残存) +``` + +### Phase 84-5 完了 + +```bash +NYASH_PHI_FALLBACK_DISABLED=1 cargo test --release --lib 2>&1 | grep "Case D" +# 期待: 出力なし(0件) + +cargo test --release --lib +# 期待: test result: ok +``` + +## タイムライン + +| Phase | 目標 | 期間 | 削減数 | 残存数 | +|-------|-----|-----|-------|-------| +| 84-1 | PHI Fallback 無効化テスト | 完了 | - | 12件 | +| 84-2 | CopyTypePropagator 実装 | 完了 ✅ | 3件 | 9件 | +| 84-3 | Edge Copy 追跡 PHI 型推論 | 1-2日 | 7件 | 2件 | +| 84-4 | 多段 PHI 型推論 | 1-2日 | 2件 | 1件 | +| 84-5 | await 暫定対応 | 30分 | 1件 | 0件 | + +**合計**: 2-4日で Case D 完全解決見込み + +## グループ別詳細 + +### GroupA: Loop 制御フロー PHI(7件) + +**パターン**: Loop + continue/break による Edge Copy 合流 + +**テスト一覧**: +1. `loop_with_continue_and_break_edge_copy_merge` (ValueId 56) +2. `nested_loop_with_multi_continue_break_edge_copy_merge` (ValueId 135) +3. `loop_inner_if_multilevel_edge_copy` (ValueId 74) +4. `loop_break_and_early_return_edge_copy` (ValueId 40) +5. `vm_exec_break_inside_if` (ValueId 27) +6. `loop_if_three_level_merge_edge_copy` (ValueId 75) +7. (7件合計) + +**解決策**: Edge Copy 追跡 PHI 型推論(Phase 84-3) + +**詳細**: [失敗パターン - GroupA](./phase84-2-failure-patterns.md#groupa-loop-制御フロー-phi7件) + +### GroupB: 多段 PHI 型推論(2件) + +**パターン**: 複数の PHI 命令が連鎖 + +**テスト一覧**: +1. `mir_stage1_cli_emit_program_min_exec_hits_type_error` (ValueId 7) +2. `mir_stage1_cli_emit_program_min_compiles_and_verifies` (ValueId 7) + +**解決策**: 再帰的 PHI 型推論(Phase 84-4) + +**詳細**: [失敗パターン - GroupB](./phase84-2-failure-patterns.md#groupb-多段-phi-型推論2件) + +### GroupC: await 特殊パターン(1件) + +**パターン**: await 式の MIR lowering + +**テスト**: +1. `test_lowering_await_expression` (ValueId 2) + +**解決策**: await 特殊ケース処理(Phase 84-5) + +**詳細**: [失敗パターン - GroupC](./phase84-2-failure-patterns.md#groupc-await-特殊パターン1件) + +## ChatGPT Pro 設計相談ポイント + +### 相談1: Edge Copy 追跡の最適化 + +- Copy チェーンの追跡深度は 10 で十分か? +- 循環 Copy 検出は必要か? +- パフォーマンス最適化(キャッシュ戦略) + +### 相談2: 多段 PHI の循環検出 + +- 循環 PHI は実際に発生するか? +- 発生する場合の処理方法(エラー or Unknown) +- visited セットの最適なデータ構造 + +### 相談3: await 型推論の長期戦略 + +- Phase 67+ async/await システムの型推論設計 +- Safepoint/Checkpoint 命令の型情報統合方法 +- 現在の暫定対応が将来の実装を妨げないか + +## 実装チェックリスト + +### Phase 84-3: Edge Copy 追跡 + +- [ ] `GenericTypeResolver::resolve_from_phi_with_copy_trace()` 実装 +- [ ] `find_copy_src()` ヘルパー関数実装 +- [ ] `trace_copy_chain()` ヘルパー関数実装 +- [ ] lifecycle.rs 統合(371行目付近) +- [ ] テスト実行: GroupA の 7件を確認 +- [ ] ドキュメント更新 + +### Phase 84-4: 多段 PHI 推論 + +- [ ] `GenericTypeResolver::resolve_from_phi_recursive()` 実装 +- [ ] 循環検出ロジック実装(HashSet) +- [ ] lifecycle.rs 統合 +- [ ] テスト実行: GroupB の 2件を確認 +- [ ] ドキュメント更新 + +### Phase 84-5: await 暫定対応 + +- [ ] lifecycle.rs に await 特殊ケース追加 +- [ ] テスト実行: GroupC の 1件を確認 +- [ ] ドキュメント更新 +- [ ] Phase 67+ 長期計画メモ作成 + +## 関連リソース + +### 過去の分析 + +- [Phase 84-1 Case D 分析](./phase84-case-d-detailed-analysis.md) - 最初の 12件分析 + +### 実装ファイル + +- `src/mir/phi_core/copy_type_propagator.rs` - Phase 84-2 実装 +- `src/mir/join_ir/lowering/generic_type_resolver.rs` - 拡張予定 +- `src/mir/builder/lifecycle.rs` - 型推論統合箇所(371行目) + +### テストファイル + +- `src/tests/loop_continue_break_no_phi_tests.rs` - GroupA-1 +- `src/tests/loop_nested_no_phi_tests.rs` - GroupA-2,3 +- `src/tests/loop_return_no_phi_tests.rs` - GroupA-4,6 +- `src/tests/mir_ctrlflow_break_continue.rs` - GroupA-5 +- `src/tests/mir_stage1_cli_emit_program_min.rs` - GroupB +- `src/mir/mod.rs:363` - GroupC + +## まとめ + +Phase 84-2 の CopyTypePropagator により 12件 → 9件に削減成功。 +残り 9件は 3つのパターンに分類され、各々に明確な解決策が提案済み。 + +Phase 84-3/4/5 の実装により、**Case D を完全解決** できる見込み。 + +--- + +**次のアクション**: Phase 84-3 の Edge Copy 追跡 PHI 型推論を実装 diff --git a/docs/development/current/main/phase84-case-d-summary.md b/docs/development/current/main/phase84-case-d-summary.md index 8c068f78..d84c2c3e 100644 --- a/docs/development/current/main/phase84-case-d-summary.md +++ b/docs/development/current/main/phase84-case-d-summary.md @@ -2,11 +2,16 @@ ## TL;DR -**現状**: 24件の Case D 失敗(52失敗中) +**現状**: 9 件の Case D 失敗(Phase 83 + Phase 84-1 + Phase 84-2 実装後) -**主要原因**: **Const命令の型アノテーション欠如** (58-67%) +**主要原因**: PHI 経由の複雑な edge パターン(await/try-catch、多段 PHI チェーンなど) -**解決策**: `constant.rs` の 5 関数に 5 行追加 → 14-16 件修正(1-2時間で完了) +**対応状況**: +- Phase 83: MethodReturnHintBox(P3-D)実装で 20 件 → 15 件 +- Phase 84-1: Const 命令型アノテーション追加で 15 件 → 12 件 +- Phase 84-2: CopyTypePropagator 導入で 12 件 → 9 件 + +**残タスク**: PHI 推論強化(Phase 84-3、PhiTypeResolver)と if_phi フォールバック縮退 --- @@ -62,30 +67,40 @@ pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId { ## 実装計画 -### Phase 84-1: Const命令型アノテーション(最優先) +### Phase 84-1: Const命令型アノテーション(完了) + +**Status**: ✅ 実装完了(40dfbc68) **ファイル**: `src/mir/builder/emission/constant.rs` **変更箇所**: 5 関数 × 1 行 = **5 行追加** -**期待効果**: Case D が 24件 → 8-10件(58-67%削減) +**効果**: Case D が 15 件 → 12 件(Const 欠如グループは解消) **所要時間**: 1-2 時間(テスト含む) **リスク**: 極めて低い(String は既に実装済み) -### Phase 84-2: Copy命令型伝播(次点) +### Phase 84-2: Copy命令型伝播(完了) + +**Status**: ✅ 実装完了(CopyTypePropagator 導入) **ファイル**: -- `src/mir/builder/ssa/local.rs` -- `src/mir/phi_core/loop_phi.rs` -- `src/mir/phi_core/if_phi.rs` +- `src/mir/phi_core/copy_type_propagator.rs`(新規箱) +- `src/mir/phi_core/mod.rs` +- `src/mir/builder/lifecycle.rs` -**期待効果**: Case D が 8-10件 → 2-4件(75-80%削減) +**内容**: +- `CopyTypePropagator` が MIR 関数内の `Copy { dst, src }` を固定点ループで走査し、 + `value_types[src]` の型を `value_types[dst]` に伝播(Unknown のみ上書き)。 +- `finalize_module` 内で return 型推論の前に実行。 -**所要時間**: 1-2 日 +**効果**: +- ベースラインテスト: 489 passed, 34 failed → 494 passed, 33 failed(+5/-1)。 +- Case D: 12 件 → 9 件(約 25% 削減)。 -**リスク**: 中(既存ロジックとの整合性確認) +**箱理論チェック**: +- 単一責務(Copy の型伝播のみ)、副作用は `value_types` 更新に限定、PHI/JoinIR には非依存。 ### Phase 84-3: PHI型推論強化(長期) @@ -99,31 +114,28 @@ pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId { ## 推奨アクション -1. **今すぐ Phase 84-1 を実装する** - - 最小限の変更で最大の効果 - - リスクも極めて低い - - 1-2 時間で完了 +1. **Phase 84-1 は完了済み** + - Const 命令の型アノテーション欠如グループは解消済み。 -2. **Phase 84-1 の効果を確認後、Phase 84-2 を検討** - - 残存ケースのパターンを分析 - - 必要な箇所にのみ型伝播を追加 +2. **Phase 84-2 も完了済み** + - Copy チェーンだけで説明できる Case D は削減済みで、残りは PHI 主体の複雑ケースに集中。 -3. **Phase 84-3 は本当に必要か検証** - - Await/Try-Catch の型推論を別途対応 - - 汎用的な多段 PHI チェーンは後回し +3. **Phase 84-3 は「PHI 強化」を必要最小限で検討** + - Await/Try-Catch や多段 PHI チェーンなど、本当に必要なパターンだけを PhiTypeResolver で扱う。 --- ## 期待される最終結果 -| Phase | Case D 件数 | 修正率 | 所要時間 | -|-------|------------|--------|---------| -| 現在 | 24 件 | 0% | - | -| Phase 84-1 後 | 8-10 件 | 58-67% | 1-2 時間 | -| Phase 84-2 後 | 2-4 件 | 92-96% | 1-2 日 | -| Phase 84-3 後 | 0-2 件 | 92-100% | 要検討 | +| Phase | Case D 件数 | 修正率 | 備考 | +|-------|------------|--------|-----| +| Phase 82 終了時 | 20 件 | - | lifecycle 修正後 | +| Phase 83 後 | 15 件 | 25% | MethodReturnHintBox(P3-D) | +| Phase 84-1 後 | 12 件 | 40% | Const 型アノテーション | +| Phase 84-2 後 | 9 件 | 55% | CopyTypePropagator | +| Phase 84-3 後(目標) | 0-2 件 | 80-100% | PhiTypeResolver(必要最小限) | -**最終目標**: テスト成功率 90% → **99-100%** +**最終目標**: Case D を 0-2 件まで縮小し、`infer_type_from_phi*` を本線から外せる状態にする。 --- diff --git a/src/mir/builder/lifecycle.rs b/src/mir/builder/lifecycle.rs index 0a89019f..367fb549 100644 --- a/src/mir/builder/lifecycle.rs +++ b/src/mir/builder/lifecycle.rs @@ -43,6 +43,8 @@ use crate::mir::join_ir::lowering::type_hint_policy::TypeHintPolicy; use crate::mir::join_ir::lowering::generic_type_resolver::GenericTypeResolver; // Phase 83: P3-D 既知メソッド戻り値型推論箱 use crate::mir::join_ir::lowering::method_return_hint::MethodReturnHintBox; +// Phase 84-2: Copy命令型伝播箱(ChatGPT Pro設計) +use crate::mir::phi_core::copy_type_propagator::CopyTypePropagator; // Phase 82: dev ガード用ヘルパー - Case 分類ロジック統一化 // @@ -303,6 +305,12 @@ 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 82-5: lifecycle.rs バグ修正 - terminator の Return のみをチェック // 問題: instructions を先に走査すると、中間値(const void 等)を誤って推論対象にしてしまう // 解決: terminator の Return のみをチェックし、実際の戻り値を正しく推論する diff --git a/src/mir/phi_core/copy_type_propagator.rs b/src/mir/phi_core/copy_type_propagator.rs new file mode 100644 index 00000000..38ee400d --- /dev/null +++ b/src/mir/phi_core/copy_type_propagator.rs @@ -0,0 +1,215 @@ +//! Phase 84-2: CopyTypePropagator — Copy命令型伝播箱(ChatGPT Pro設計) +//! +//! # 責務 +//! +//! Copy命令の型伝播のみを担当する専用箱。 +//! 固定点ループで Copy チェーン全体に型を伝播させる。 +//! +//! # 設計原則(箱理論) +//! +//! - **単一責務**: Copy命令の型伝播のみ +//! - **固定点ループ**: 変化がなくなるまで反復 +//! - **副作用限定**: value_types のみ更新 +//! +//! # アルゴリズム +//! +//! 1. 関数内の全 Copy 命令を走査 +//! 2. src の型が既知 & dst の型が未知 → dst に型を伝播 +//! 3. 変化がなくなるまで繰り返す(固定点) +//! +//! # 使用例 +//! +//! ```ignore +//! // lifecycle.rs から呼び出し +//! CopyTypePropagator::propagate(&function, &mut value_types); +//! ``` + +use crate::mir::{MirFunction, MirInstruction, MirType, ValueId}; +use std::collections::BTreeMap; + +/// Phase 84-2: Copy命令型伝播箱 +/// +/// Copy チェーン: v1 → v2 → v3 で v1 の型が既知なら v2, v3 にも伝播。 +/// Loop exit や If merge の edge copy で発生する型欠如を解消する。 +pub struct CopyTypePropagator; + +impl CopyTypePropagator { + /// Copy命令の型を固定点ループで伝播 + /// + /// # 引数 + /// + /// - `function`: MIR 関数 + /// - `value_types`: 型マップ(更新される) + /// + /// # 戻り値 + /// + /// 伝播された型の数 + pub fn propagate(function: &MirFunction, value_types: &mut BTreeMap) -> usize { + let mut total_propagated = 0usize; + + // 固定点ループ: 変化がなくなるまで反復 + loop { + let propagated = Self::propagate_single_pass(function, value_types); + if propagated == 0 { + break; + } + total_propagated += propagated; + + // 無限ループ防止(理論上は不要だが安全策) + if total_propagated > 10000 { + if std::env::var("NYASH_COPY_PROP_DEBUG").is_ok() { + eprintln!("[copy_prop] warning: exceeded 10000 propagations, stopping"); + } + break; + } + } + + if std::env::var("NYASH_COPY_PROP_DEBUG").is_ok() && total_propagated > 0 { + eprintln!( + "[copy_prop] {} total types propagated for function {}", + total_propagated, function.signature.name + ); + } + + total_propagated + } + + /// 1パスの型伝播(内部用) + fn propagate_single_pass( + function: &MirFunction, + value_types: &mut BTreeMap, + ) -> usize { + let mut propagated = 0usize; + + for (_bid, bb) in function.blocks.iter() { + for inst in bb.instructions.iter() { + if let MirInstruction::Copy { dst, src } = inst { + // src の型が既知 & dst の型が未知 → 伝播 + if !value_types.contains_key(dst) { + if let Some(src_type) = value_types.get(src).cloned() { + value_types.insert(*dst, src_type.clone()); + propagated += 1; + + if std::env::var("NYASH_COPY_PROP_TRACE").is_ok() { + eprintln!( + "[copy_prop] {:?} <- {:?} : {:?}", + dst, src, src_type + ); + } + } + } + } + } + } + + propagated + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::mir::{BasicBlock, BasicBlockId, MirFunction, FunctionSignature, EffectMask}; + + fn make_test_function() -> MirFunction { + let sig = FunctionSignature { + name: "test".to_string(), + params: vec![], + return_type: MirType::Void, + effects: EffectMask::PURE, + }; + MirFunction::new(sig, BasicBlockId::new(0)) + } + + #[test] + fn test_single_copy_propagation() { + let mut f = make_test_function(); + let mut value_types = BTreeMap::new(); + + // Setup: v1 has type Integer, Copy v2 <- v1 + value_types.insert(ValueId(1), MirType::Integer); + + let mut bb = BasicBlock::new(BasicBlockId::new(0)); + bb.instructions.push(MirInstruction::Copy { + dst: ValueId(2), + src: ValueId(1), + }); + f.blocks.insert(BasicBlockId::new(0), bb); + + // Propagate + let count = CopyTypePropagator::propagate(&f, &mut value_types); + + assert_eq!(count, 1); + assert_eq!(value_types.get(&ValueId(2)), Some(&MirType::Integer)); + } + + #[test] + fn test_chain_copy_propagation() { + let mut f = make_test_function(); + let mut value_types = BTreeMap::new(); + + // Setup: v1 -> v2 -> v3 chain + value_types.insert(ValueId(1), MirType::String); + + let mut bb = BasicBlock::new(BasicBlockId::new(0)); + bb.instructions.push(MirInstruction::Copy { + dst: ValueId(2), + src: ValueId(1), + }); + bb.instructions.push(MirInstruction::Copy { + dst: ValueId(3), + src: ValueId(2), + }); + f.blocks.insert(BasicBlockId::new(0), bb); + + // Propagate (needs 2 iterations for chain) + let count = CopyTypePropagator::propagate(&f, &mut value_types); + + assert_eq!(count, 2); + assert_eq!(value_types.get(&ValueId(2)), Some(&MirType::String)); + assert_eq!(value_types.get(&ValueId(3)), Some(&MirType::String)); + } + + #[test] + fn test_no_propagation_when_dst_has_type() { + let mut f = make_test_function(); + let mut value_types = BTreeMap::new(); + + // Setup: both v1 and v2 already have types + value_types.insert(ValueId(1), MirType::Integer); + value_types.insert(ValueId(2), MirType::Bool); // already typed + + let mut bb = BasicBlock::new(BasicBlockId::new(0)); + bb.instructions.push(MirInstruction::Copy { + dst: ValueId(2), + src: ValueId(1), + }); + f.blocks.insert(BasicBlockId::new(0), bb); + + // Propagate - should not overwrite existing type + let count = CopyTypePropagator::propagate(&f, &mut value_types); + + assert_eq!(count, 0); + assert_eq!(value_types.get(&ValueId(2)), Some(&MirType::Bool)); + } + + #[test] + fn test_no_propagation_when_src_unknown() { + let mut f = make_test_function(); + let mut value_types = BTreeMap::new(); + + // Setup: v1 has no type, Copy v2 <- v1 + let mut bb = BasicBlock::new(BasicBlockId::new(0)); + bb.instructions.push(MirInstruction::Copy { + dst: ValueId(2), + src: ValueId(1), + }); + f.blocks.insert(BasicBlockId::new(0), bb); + + // Propagate - nothing to propagate + let count = CopyTypePropagator::propagate(&f, &mut value_types); + + assert_eq!(count, 0); + assert_eq!(value_types.get(&ValueId(2)), None); + } +} diff --git a/src/mir/phi_core/mod.rs b/src/mir/phi_core/mod.rs index 7e61df32..0b38654f 100644 --- a/src/mir/phi_core/mod.rs +++ b/src/mir/phi_core/mod.rs @@ -29,6 +29,9 @@ pub mod loopform_builder; // Phase 26-E: PHI SSOT Unification - PhiBuilderBox pub mod phi_builder_box; +// Phase 84-2: Copy命令型伝播箱(ChatGPT Pro設計) +pub mod copy_type_propagator; + // Phase 35-5: if_body_local_merge 削除(PhiBuilderBoxに吸収済み) // Phase 35-5: phi_invariants 削除(JoinIR Verifierに移譲済み)