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>
This commit is contained in:
434
docs/development/current/main/phase84-2-case-d-investigation.md
Normal file
434
docs/development/current/main/phase84-2-case-d-investigation.md
Normal file
@ -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<ValueId, MirType>,
|
||||||
|
) -> Option<MirType> {
|
||||||
|
// 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<ValueId, MirType>,
|
||||||
|
max_depth: usize,
|
||||||
|
) -> Option<MirType> {
|
||||||
|
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<ValueId, MirType>,
|
||||||
|
visited: &mut HashSet<ValueId>,
|
||||||
|
) -> Option<MirType> {
|
||||||
|
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 を完全解決** できる見込み。
|
||||||
390
docs/development/current/main/phase84-2-failure-patterns.md
Normal file
390
docs/development/current/main/phase84-2-failure-patterns.md
Normal file
@ -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<ValueId, MirType>,
|
||||||
|
visited: &mut HashSet<ValueId>,
|
||||||
|
) -> Option<MirType> {
|
||||||
|
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
|
||||||
|
```
|
||||||
211
docs/development/current/main/phase84-2-summary.md
Normal file
211
docs/development/current/main/phase84-2-summary.md
Normal file
@ -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<ValueId, MirType>,
|
||||||
|
) {
|
||||||
|
// 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<ValueId, MirType>,
|
||||||
|
) -> Option<MirType> {
|
||||||
|
// 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)
|
||||||
120
docs/development/current/main/phase84-2-test-list.md
Normal file
120
docs/development/current/main/phase84-2-test-list.md
Normal file
@ -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 <test_name>
|
||||||
|
|
||||||
|
# 詳細ログ
|
||||||
|
RUST_LOG=debug cargo test --release --lib <test_name>
|
||||||
|
|
||||||
|
# バックトレース
|
||||||
|
RUST_BACKTRACE=1 cargo test --release --lib <test_name>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 次のステップ
|
||||||
|
|
||||||
|
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)
|
||||||
@ -2,10 +2,14 @@
|
|||||||
|
|
||||||
## 概要
|
## 概要
|
||||||
|
|
||||||
Phase 83 で Case D が 20件 → **24件** に増加(調査時点)。
|
Phase 83 で Case D が 20 件 → **15 件** に減少(MethodReturnHintBox 実装)。
|
||||||
本レポートでは全 24 件の Case D 失敗を詳細に分析し、不足している型推論パターンを特定する。
|
その後 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
|
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件)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
237
docs/development/current/main/phase84-case-d-index.md
Normal file
237
docs/development/current/main/phase84-case-d-index.md
Normal file
@ -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<ValueId, MirType>,
|
||||||
|
) -> Option<MirType> {
|
||||||
|
// 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<ValueId>)
|
||||||
|
- [ ] 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 型推論を実装
|
||||||
@ -2,11 +2,16 @@
|
|||||||
|
|
||||||
## TL;DR
|
## 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`
|
**ファイル**: `src/mir/builder/emission/constant.rs`
|
||||||
|
|
||||||
**変更箇所**: 5 関数 × 1 行 = **5 行追加**
|
**変更箇所**: 5 関数 × 1 行 = **5 行追加**
|
||||||
|
|
||||||
**期待効果**: Case D が 24件 → 8-10件(58-67%削減)
|
**効果**: Case D が 15 件 → 12 件(Const 欠如グループは解消)
|
||||||
|
|
||||||
**所要時間**: 1-2 時間(テスト含む)
|
**所要時間**: 1-2 時間(テスト含む)
|
||||||
|
|
||||||
**リスク**: 極めて低い(String は既に実装済み)
|
**リスク**: 極めて低い(String は既に実装済み)
|
||||||
|
|
||||||
### Phase 84-2: Copy命令型伝播(次点)
|
### Phase 84-2: Copy命令型伝播(完了)
|
||||||
|
|
||||||
|
**Status**: ✅ 実装完了(CopyTypePropagator 導入)
|
||||||
|
|
||||||
**ファイル**:
|
**ファイル**:
|
||||||
- `src/mir/builder/ssa/local.rs`
|
- `src/mir/phi_core/copy_type_propagator.rs`(新規箱)
|
||||||
- `src/mir/phi_core/loop_phi.rs`
|
- `src/mir/phi_core/mod.rs`
|
||||||
- `src/mir/phi_core/if_phi.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型推論強化(長期)
|
### Phase 84-3: PHI型推論強化(長期)
|
||||||
|
|
||||||
@ -99,31 +114,28 @@ pub fn emit_integer(b: &mut MirBuilder, val: i64) -> ValueId {
|
|||||||
|
|
||||||
## 推奨アクション
|
## 推奨アクション
|
||||||
|
|
||||||
1. **今すぐ Phase 84-1 を実装する**
|
1. **Phase 84-1 は完了済み**
|
||||||
- 最小限の変更で最大の効果
|
- Const 命令の型アノテーション欠如グループは解消済み。
|
||||||
- リスクも極めて低い
|
|
||||||
- 1-2 時間で完了
|
|
||||||
|
|
||||||
2. **Phase 84-1 の効果を確認後、Phase 84-2 を検討**
|
2. **Phase 84-2 も完了済み**
|
||||||
- 残存ケースのパターンを分析
|
- Copy チェーンだけで説明できる Case D は削減済みで、残りは PHI 主体の複雑ケースに集中。
|
||||||
- 必要な箇所にのみ型伝播を追加
|
|
||||||
|
|
||||||
3. **Phase 84-3 は本当に必要か検証**
|
3. **Phase 84-3 は「PHI 強化」を必要最小限で検討**
|
||||||
- Await/Try-Catch の型推論を別途対応
|
- Await/Try-Catch や多段 PHI チェーンなど、本当に必要なパターンだけを PhiTypeResolver で扱う。
|
||||||
- 汎用的な多段 PHI チェーンは後回し
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 期待される最終結果
|
## 期待される最終結果
|
||||||
|
|
||||||
| Phase | Case D 件数 | 修正率 | 所要時間 |
|
| Phase | Case D 件数 | 修正率 | 備考 |
|
||||||
|-------|------------|--------|---------|
|
|-------|------------|--------|-----|
|
||||||
| 現在 | 24 件 | 0% | - |
|
| Phase 82 終了時 | 20 件 | - | lifecycle 修正後 |
|
||||||
| Phase 84-1 後 | 8-10 件 | 58-67% | 1-2 時間 |
|
| Phase 83 後 | 15 件 | 25% | MethodReturnHintBox(P3-D) |
|
||||||
| Phase 84-2 後 | 2-4 件 | 92-96% | 1-2 日 |
|
| Phase 84-1 後 | 12 件 | 40% | Const 型アノテーション |
|
||||||
| Phase 84-3 後 | 0-2 件 | 92-100% | 要検討 |
|
| 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*` を本線から外せる状態にする。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,8 @@ use crate::mir::join_ir::lowering::type_hint_policy::TypeHintPolicy;
|
|||||||
use crate::mir::join_ir::lowering::generic_type_resolver::GenericTypeResolver;
|
use crate::mir::join_ir::lowering::generic_type_resolver::GenericTypeResolver;
|
||||||
// Phase 83: P3-D 既知メソッド戻り値型推論箱
|
// Phase 83: P3-D 既知メソッド戻り値型推論箱
|
||||||
use crate::mir::join_ir::lowering::method_return_hint::MethodReturnHintBox;
|
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 分類ロジック統一化
|
// Phase 82: dev ガード用ヘルパー - Case 分類ロジック統一化
|
||||||
//
|
//
|
||||||
@ -303,6 +305,12 @@ impl super::MirBuilder {
|
|||||||
let mut module = self.current_module.take().unwrap();
|
let mut module = self.current_module.take().unwrap();
|
||||||
let mut function = self.current_function.take().unwrap();
|
let mut function = self.current_function.take().unwrap();
|
||||||
function.metadata.value_types = self.value_types.clone();
|
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 のみをチェック
|
// Phase 82-5: lifecycle.rs バグ修正 - terminator の Return のみをチェック
|
||||||
// 問題: instructions を先に走査すると、中間値(const void 等)を誤って推論対象にしてしまう
|
// 問題: instructions を先に走査すると、中間値(const void 等)を誤って推論対象にしてしまう
|
||||||
// 解決: terminator の Return のみをチェックし、実際の戻り値を正しく推論する
|
// 解決: terminator の Return のみをチェックし、実際の戻り値を正しく推論する
|
||||||
|
|||||||
215
src/mir/phi_core/copy_type_propagator.rs
Normal file
215
src/mir/phi_core/copy_type_propagator.rs
Normal file
@ -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<ValueId, MirType>) -> 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<ValueId, MirType>,
|
||||||
|
) -> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -29,6 +29,9 @@ pub mod loopform_builder;
|
|||||||
// Phase 26-E: PHI SSOT Unification - PhiBuilderBox
|
// Phase 26-E: PHI SSOT Unification - PhiBuilderBox
|
||||||
pub mod phi_builder_box;
|
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: if_body_local_merge 削除(PhiBuilderBoxに吸収済み)
|
||||||
// Phase 35-5: phi_invariants 削除(JoinIR Verifierに移譲済み)
|
// Phase 35-5: phi_invariants 削除(JoinIR Verifierに移譲済み)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user