diff --git a/CURRENT_TASK.md b/CURRENT_TASK.md index d972907b..9590aa2c 100644 --- a/CURRENT_TASK.md +++ b/CURRENT_TASK.md @@ -26,7 +26,8 @@ - debug-only: Exit PHI collision を早期検出する verifier を追加(LLVM 実行時に壊れる前に Fail-Fast) - **Phase 133 完了**: Promoted carrier の `join_id` 解決(Trim)を SSOT に寄せて根治(smoke は compile-only)。 - **Phase 134 完了**: Plugin loader best-effort loading(決定的順序 + failure 集約 + 継続)を導入。 -- **Phase 135 実装**: ConditionLoweringBox が allocator SSOT を無視して ValueId 衝突を起こす問題を根治(検証はローカルで実施)。 +- **Phase 135 完了**: ConditionLoweringBox allocator SSOT(P0: 根治修正 + P1: contract_checks Fail-Fast 強化)。 +- **Phase 136 完了**: ValueId allocator SSOT 徹底(関数内経路から `value_gen.next()` 掃討完了)。 - **Phase 88 完了**: continue + 可変ステップ(i=i+const 差分)を dev-only fixture で固定、StepCalculator Box 抽出。 - **Phase 89 完了**: P0(ContinueReturn detector)+ P1(lowering 実装)完了。 - **Phase 90 完了**: ParseStringComposite + `Null` literal + ContinueReturn(同一値の複数 return-if)を dev-only fixture で固定。 diff --git a/docs/development/current/main/phases/README.md b/docs/development/current/main/phases/README.md index 73b384b2..a07eb480 100644 --- a/docs/development/current/main/phases/README.md +++ b/docs/development/current/main/phases/README.md @@ -8,6 +8,7 @@ - **Phase 133**: Promoted carrier join_id(Trim)修正 - **Phase 134**: Plugin loader best-effort loading - **Phase 135**: ConditionLoweringBox allocator SSOT(ValueId 衝突の根治) +- **Phase 136**: ValueId allocator SSOT 徹底(残存 value_gen.next() 掃討) ## Phase フォルダ構成(推奨) diff --git a/docs/development/current/main/phases/phase-136/README.md b/docs/development/current/main/phases/phase-136/README.md new file mode 100644 index 00000000..99618fcd --- /dev/null +++ b/docs/development/current/main/phases/phase-136/README.md @@ -0,0 +1,36 @@ +# Phase 136: ValueId allocator SSOT 徹底(残存 value_gen.next() 掃討) + +## Status +- 状態: ✅ P0 完了 +- スコープ: 関数内 ValueId 発行を `MirBuilder::next_value_id()` に一本化し、予約PHI/引数/ローカルとの衝突余地を消す + +## Problem +Phase 135 で契約(allocator SSOT)は固まったが、一部のコードで `builder.value_gen.next()` を直接使用していた。 +これは関数内で走る場合、予約PHI dst や関数引数との ValueId 衝突を引き起こす可能性がある。 + +## Fix + +### SSOT 化対象 +1. **`src/mir/builder.rs:new_typed_value()`** - 型付きValueId発行API + - Before: `let id = self.value_gen.next();` + - After: `let id = self.next_value_id();` (関数コンテキストを尊重) + +2. **テストコード内の `value_gen.next()`** - 関数スコープをシミュレート + - `test_shadowing_binding_restore`: 関数スコープシミュレーションで `next_value_id()` を使用 + - `test_valueid_binding_parallel_allocation`: SSOT allocator を使用(Module context フォールバック維持) + +### OK(Module context フォールバック) +以下は既に `if current_function.is_some()` で関数コンテキストを判定しており、Module context のフォールバックとして `value_gen.next()` を使用(OK): +- `src/mir/builder/utils.rs:next_value_id()` - SSOT allocator 自体(43行目) +- `src/mir/builder/utils.rs:pin_to_slot()` - 436行目 +- `src/mir/builder/utils.rs:materialize_local()` - 467行目 +- `src/mir/utils/phi_helpers.rs:insert_phi_unified()` - 69行目 + +## Acceptance +- ✅ `rg -n "value_gen\.next\(" src/mir` で関数内経路から消える +- ✅ `cargo test --release --lib` - 997 passed +- ✅ `phase135_trim_mir_verify.sh` - PASS +- ✅ `phase132_exit_phi_parity.sh` - 3/3 PASS + +## Remaining Tasks(残課題) +なし。全ての関数内経路から `value_gen.next()` を排除完了。Module context のフォールバックは意図的に残す。 diff --git a/src/mir/builder.rs b/src/mir/builder.rs index 481a0c12..130568f5 100644 --- a/src/mir/builder.rs +++ b/src/mir/builder.rs @@ -1064,8 +1064,9 @@ impl MirBuilder { // ============================================================================ /// 型付きValueIdを発行(新API) + /// Phase 136 P0: Use SSOT allocator (next_value_id) to respect function context pub fn new_typed_value(&mut self, kind: super::MirValueKind) -> super::TypedValueId { - let id = self.value_gen.next(); + let id = self.next_value_id(); self.value_kinds.insert(id, kind); super::TypedValueId::new(id, kind) } @@ -1156,7 +1157,8 @@ mod binding_id_tests { builder.push_lexical_scope(); // Declare outer x - let outer_vid = builder.value_gen.next(); + // Phase 136 P0: Use SSOT allocator for function scope simulation + let outer_vid = builder.next_value_id(); builder .declare_local_in_current_scope("x", outer_vid) .unwrap(); @@ -1165,7 +1167,8 @@ mod binding_id_tests { // Enter inner scope and shadow x builder.push_lexical_scope(); - let inner_vid = builder.value_gen.next(); + // Phase 136 P0: Use SSOT allocator for function scope simulation + let inner_vid = builder.next_value_id(); builder .declare_local_in_current_scope("x", inner_vid) .unwrap(); @@ -1186,10 +1189,13 @@ mod binding_id_tests { fn test_valueid_binding_parallel_allocation() { let mut builder = MirBuilder::new(); + // Phase 136 P0: Use SSOT allocator (next_value_id) + // Note: Without current_function, next_value_id() falls back to value_gen.next() + // so this test still validates ValueId/BindingId independence // Allocate ValueIds and BindingIds in parallel - let vid0 = builder.value_gen.next(); + let vid0 = builder.next_value_id(); let bid0 = builder.allocate_binding_id(); - let vid1 = builder.value_gen.next(); + let vid1 = builder.next_value_id(); let bid1 = builder.allocate_binding_id(); // ValueId and BindingId should be independent @@ -1199,15 +1205,15 @@ mod binding_id_tests { assert_eq!(bid1.raw(), 1); // Allocating more ValueIds should not affect BindingId counter - let _ = builder.value_gen.next(); - let _ = builder.value_gen.next(); + let _ = builder.next_value_id(); + let _ = builder.next_value_id(); let bid2 = builder.allocate_binding_id(); assert_eq!(bid2.raw(), 2); // Still sequential // Allocating more BindingIds should not affect ValueId counter let _ = builder.allocate_binding_id(); let _ = builder.allocate_binding_id(); - let vid2 = builder.value_gen.next(); + let vid2 = builder.next_value_id(); assert_eq!(vid2.0, 4); // Continues from where we left off } }