Files
hakorune/docs/development/current/main/phase229-action-plan.md
nyash-codex d4f90976da refactor(joinir): Phase 244 - ConditionLoweringBox trait unification
Unify condition lowering logic across Pattern 2/4 with trait-based API.

New infrastructure:
- condition_lowering_box.rs: ConditionLoweringBox trait + ConditionContext (293 lines)
- ExprLowerer implements ConditionLoweringBox trait (+51 lines)

Pattern migrations:
- Pattern 2 (loop_with_break_minimal.rs): Use trait API
- Pattern 4 (loop_with_continue_minimal.rs): Use trait API

Benefits:
- Unified condition lowering interface
- Extensible for future lowering strategies
- Clean API boundary between patterns and lowering logic
- Zero code duplication

Test results: 911/911 PASS (+2 new tests)

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 02:35:31 +09:00

400 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Phase 229 アクションプラン: ConditionAlias 削除
## 🎯 目標
**ConditionAlias 型を削除し、CarrierInfo を簡素化する**
- 削減: CarrierInfo のフィールド 6 → 5
- 効果: データ整合性チェック箇所 3 → 1
- 時間: 1〜2時間
- リスク: 低
## 📋 実装手順
### Step 1: resolve 関数実装 (15分)
**ファイル**: `src/mir/join_ir/lowering/carrier_info.rs`
```rust
impl CarrierInfo {
/// Phase 229: Resolve promoted LoopBodyLocal carrier name
///
/// # Arguments
///
/// * `old_name` - Original LoopBodyLocal variable name (e.g., "digit_pos")
///
/// # Returns
///
/// * `Some(carrier_name)` - If this variable was promoted (e.g., "is_digit_pos")
/// * `None` - If not a promoted variable
///
/// # Design
///
/// Uses naming convention: "var_name" → "is_var_name"
/// Alternative: Linear search in carriers with original_name field
pub fn resolve_promoted_carrier(&self, old_name: &str) -> Option<&str> {
// Check if this variable was promoted
if !self.promoted_loopbodylocals.contains(&old_name.to_string()) {
return None;
}
// Naming convention: "digit_pos" → "is_digit_pos"
let expected_name = format!("is_{}", old_name);
self.carriers.iter()
.find(|c| c.name == expected_name)
.map(|c| c.name.as_str())
}
}
```
**追加箇所**: line 420 付近CarrierInfo impl ブロックの最後)
---
### Step 2: pattern2_with_break.rs 修正 (20分)
**ファイル**: `src/mir/builder/control_flow/joinir/patterns/pattern2_with_break.rs`
**削除** (line 354-391):
```rust
// Phase 224-D: Add condition aliases to ConditionEnv
// This allows promoted variables to be referenced by their original names in conditions
for alias in &carrier_info.condition_aliases {
// ... 約40行削除
}
```
**追加** (line 354):
```rust
// Phase 229: Resolve promoted LoopBodyLocal variables dynamically
// This replaces condition_aliases with on-demand resolution
for promoted_var in &carrier_info.promoted_loopbodylocals {
if let Some(carrier_name) = carrier_info.resolve_promoted_carrier(promoted_var) {
// Find carrier's join_id in carriers list (BEFORE filtering, with join_ids)
if let Some(carrier) = carriers_with_join_ids.iter().find(|c| c.name == carrier_name) {
if let Some(join_id) = carrier.join_id {
// Add dynamic mapping: old_name → carrier's join_id
env.insert(promoted_var.clone(), join_id);
eprintln!(
"[pattern2/phase229] Resolved promoted variable '{}' → carrier '{}' (join_id={:?})",
promoted_var, carrier_name, join_id
);
} else {
eprintln!(
"[pattern2/phase229] WARNING: Promoted carrier '{}' has no join_id yet!",
carrier_name
);
}
} else {
eprintln!(
"[pattern2/phase229] WARNING: Promoted carrier '{}' not found in carriers list",
carrier_name
);
}
}
}
```
---
### Step 3: Promoter 修正 (20分)
#### 3-1. Trim Promoter
**ファイル**: `src/mir/loop_pattern_detection/loop_body_carrier_promoter.rs`
**削除** (line 87-90):
```rust
carrier_info.condition_aliases.push(crate::mir::join_ir::lowering::carrier_info::ConditionAlias {
old_name: trimmed_var_name.to_string(),
carrier_name: carrier_var_name.clone(),
});
```
**コメント追加** (line 87):
```rust
// Phase 229: promoted_loopbodylocals already records this promotion
// No need for condition_aliases - resolved dynamically via CarrierInfo::resolve_promoted_carrier()
```
#### 3-2. DigitPos Promoter
**ファイル**: `src/mir/loop_pattern_detection/loop_body_digitpos_promoter.rs`
**削除** (line 203-206):
```rust
carrier_info.condition_aliases.push(crate::mir::join_ir::lowering::carrier_info::ConditionAlias {
old_name: var_name.to_string(),
carrier_name: carrier_var_name.clone(),
});
```
**コメント追加** (line 203):
```rust
// Phase 229: promoted_loopbodylocals already records this promotion
// No need for condition_aliases - resolved dynamically via CarrierInfo::resolve_promoted_carrier()
```
---
### Step 4: ConditionAlias 型削除 (10分)
**ファイル**: `src/mir/join_ir/lowering/carrier_info.rs`
**削除** (line 85-101):
```rust
/// Phase 224-D: Condition alias for promoted LoopBodyLocal variables
///
/// Maps old variable names to their promoted carrier names for condition resolution.
/// ...
#[derive(Debug, Clone)]
pub struct ConditionAlias {
pub old_name: String,
pub carrier_name: String,
}
```
**削除** (line 195):
```rust
pub condition_aliases: Vec<ConditionAlias>,
```
**削除** (各 constructor で):
- line 259: `condition_aliases: Vec::new(),`
- line 320: `condition_aliases: Vec::new(),`
- line 348: `condition_aliases: Vec::new(),`
- line 410-414: `merge_other()` の condition_aliases マージコード
---
### Step 5: pattern4_carrier_analyzer.rs 修正 (5分)
**ファイル**: `src/mir/builder/control_flow/joinir/patterns/pattern4_carrier_analyzer.rs`
**削除** (line 76):
```rust
condition_aliases: all_carriers.condition_aliases.clone(), // Phase 224-D
```
**削除** (line 299):
```rust
condition_aliases: Vec::new(), // Phase 224-D
```
---
### Step 6: pattern_pipeline.rs 修正 (5分)
**ファイル**: `src/mir/builder/control_flow/joinir/patterns/pattern_pipeline.rs`
**削除** (line 412):
```rust
condition_aliases: Vec::new(), // Phase 224-D
```
**削除** (line 452):
```rust
condition_aliases: Vec::new(), // Phase 224-D
```
---
## ✅ テスト手順
### Level 1: ビルド確認 (5分)
```bash
cargo build --release 2>&1 | tee /tmp/phase229-build.log
# エラーがないことを確認
```
### Level 2: 単体テスト (5分)
```bash
# CarrierInfo resolve テスト(手動確認)
cargo test --lib carrier_info -- --nocapture
# Pattern detection テスト
cargo test --lib loop_pattern_detection -- --nocapture
```
### Level 3: パターンテスト (10分)
```bash
# Trim pattern
cargo test --release test_mir_joinir_funcscanner_trim 2>&1 | tee /tmp/phase229-trim.log
# DigitPos pattern
cargo test --release test_loopbodylocal_digitpos 2>&1 | tee /tmp/phase229-digitpos.log
# Pattern 2 (break) integration
cargo test --release test_loop_with_break 2>&1 | tee /tmp/phase229-pattern2.log
```
### Level 4: 決定性テスト (10分)
```bash
# 3回実行して ValueId が変わらないことを確認
for i in 1 2 3; do
echo "=== Run $i ===" | tee -a /tmp/phase229-determinism.log
cargo test --release test_loop_with_break 2>&1 | grep -E "ValueId|test result" | tee -a /tmp/phase229-determinism.log
done
# 3回の出力が同一であることを確認
```
### Level 5: E2E テスト (20分)
```bash
# Smoke tests (loop 関連のみ)
tools/smokes/v2/run.sh --profile quick --filter "loop_*" 2>&1 | tee /tmp/phase229-smoke.log
# Full MIR test suite
cargo test --release --test '*' 2>&1 | grep -E "(test result|FAILED)" | tee /tmp/phase229-full.log
```
---
## 🎯 成功条件
### ビルド
- ✅ cargo build --release が成功
- ✅ 警告 0 件unused imports, dead code など)
### テスト
- ✅ Trim pattern テストが PASS
- ✅ DigitPos pattern テストが PASS
- ✅ Pattern 2 integration テストが PASS
- ✅ 決定性テスト3回実行で同じ ValueId
### コード品質
- ✅ CarrierInfo のフィールド数: 6 → 5
- ✅ condition_aliases 参照: 15箇所 → 0箇所
- ✅ 新しいドキュメントコメント追加
---
## 📝 コミットメッセージ
```
refactor(joinir): Phase 229 - Remove redundant ConditionAlias
Problem:
- ConditionAlias duplicates information already in promoted_loopbodylocals
- Maintaining 3 data structures (promoted_loopbodylocals, carriers, condition_aliases) is error-prone
- confusion: "Why do we need condition_aliases when we have promoted_loopbodylocals?"
Solution:
- Add CarrierInfo::resolve_promoted_carrier() for dynamic resolution
- Remove ConditionAlias type and all usages
- Use promoted_loopbodylocals + naming convention ("var" → "is_var")
Impact:
- CarrierInfo fields: 6 → 5
- Maintenance cost: 3 data structures → 2
- No functional changes (all tests pass)
Files changed:
- carrier_info.rs: Added resolve_promoted_carrier(), removed ConditionAlias
- pattern2_with_break.rs: Dynamic resolution instead of condition_aliases
- loop_body_carrier_promoter.rs: Removed condition_aliases.push()
- loop_body_digitpos_promoter.rs: Removed condition_aliases.push()
- pattern4_carrier_analyzer.rs: Removed condition_aliases fields
- pattern_pipeline.rs: Removed condition_aliases fields
Tests:
- ✅ test_mir_joinir_funcscanner_trim
- ✅ test_loopbodylocal_digitpos
- ✅ test_loop_with_break
- ✅ Determinism test (3 runs with same ValueId)
```
---
## 🚨 リスク管理
### 低リスク要因
1. **既存のテストで検証可能**
- Trim pattern テスト
- DigitPos pattern テスト
- Pattern 2 integration テスト
2. **影響範囲が明確**
- CarrierInfo とその使用箇所のみ
- MIR generation ロジックは変更なし
3. **後方互換性**
- promoted_loopbodylocals は残る
- CarrierVar.role は残る
- 外部インターフェース変更なし
### もしもの時の対処
**ビルドエラー**:
```bash
# condition_aliases の参照が残っていたら
rg "condition_aliases" src/mir --type rust
# 漏れを修正
```
**テスト失敗**:
```bash
# ログを確認
cat /tmp/phase229-pattern2.log | grep -E "ERROR|FAILED|panic"
# resolve が失敗していたら
# → 命名規則の確認("is_" prefix
# → promoted_loopbodylocals に記録されているか確認
```
**決定性失敗**:
```bash
# 3回実行で ValueId が異なる場合
# → Phase 229 の変更は関係なし(元々の問題)
# → git log で最近の HashMap 変更をチェック
```
---
## 📊 見積もり
| タスク | 時間 |
|-------|-----|
| Step 1: resolve 実装 | 15分 |
| Step 2: pattern2 修正 | 20分 |
| Step 3: Promoter 修正 | 20分 |
| Step 4-6: 型削除 | 20分 |
| テスト実行 | 50分 |
| ドキュメント更新 | 15分 |
| **合計** | **2時間20分** |
---
## ✅ チェックリスト
実装時にこのリストを確認:
- [ ] Step 1: CarrierInfo::resolve_promoted_carrier() 実装
- [ ] Step 2: pattern2_with_break.rs の condition_aliases ループ削除
- [ ] Step 3-1: loop_body_carrier_promoter.rs の condition_aliases.push() 削除
- [ ] Step 3-2: loop_body_digitpos_promoter.rs の condition_aliases.push() 削除
- [ ] Step 4: ConditionAlias 型削除
- [ ] Step 5: pattern4_carrier_analyzer.rs 修正
- [ ] Step 6: pattern_pipeline.rs 修正
- [ ] Level 1: ビルド確認
- [ ] Level 2: 単体テスト
- [ ] Level 3: パターンテストTrim, DigitPos, Pattern 2
- [ ] Level 4: 決定性テスト3回実行
- [ ] Level 5: E2E テストSmoke + Full
- [ ] コミットメッセージ作成
- [ ] CURRENT_TASK.md 更新
---
**作成日**: 2025-12-10
**対象**: Phase 229 実装
**前提**: Phase 227-228 完了
Status: Active
Scope: アクションプランJoinIR/ExprLowerer ライン)