refactor(joinir): Phase 287 P0.1 - Move verification to debug_assertions
- Move verify_no_phi_dst_overwrite() to debug_assertions.rs - Move verify_phi_inputs_defined() to debug_assertions.rs - Move verify_joinir_contracts() to debug_assertions.rs - Remove duplicate get_instruction_dst() from mod.rs - mod.rs: 1,555 → ~1,380 lines (-176 lines) - Semantic invariance: 154/154 smoke tests PASS, Pattern6 RC:9 Phase 287 P0: Big Files Refactoring (意味論不変) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -8,6 +8,7 @@
|
||||
- `./tools/smokes/v2/run.sh --profile quick` 154/154 PASS 維持
|
||||
- 入口: `docs/development/current/main/phases/phase-188.3/README.md`
|
||||
- 次の指示書(refactor挟み込み): `docs/development/current/main/phases/phase-188.3/P2-REFACTORING-INSTRUCTIONS.md`
|
||||
- 次の指示書(でかいファイル分割): `docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md`
|
||||
|
||||
**2025-12-27: Phase 188.2 完了** ✅
|
||||
- StepTreeの `max_loop_depth` を SSOT に採用(Option A)
|
||||
|
||||
@ -0,0 +1,137 @@
|
||||
# Phase 287 P0: Big Files Refactoring 指示書(意味論不変 / 推定の削減)
|
||||
|
||||
**Date**: 2025-12-27
|
||||
**Scope**: Rust 側の“でかいファイル”を分割して、推定(heuristics)依存を減らす
|
||||
**Non-goals**: 新機能、既定挙動変更、silent fallback 追加、env var 追加
|
||||
|
||||
---
|
||||
|
||||
## 目的(SSOT)
|
||||
|
||||
- “推定で決めている箇所” を減らし、境界・契約・入口を SSOT として明文化する。
|
||||
- **意味論不変**で分割し、将来の拡張(Pattern6 generalize / merge 強化)に備える。
|
||||
|
||||
---
|
||||
|
||||
## 前提(現状の到達点)
|
||||
|
||||
- Pattern6 の事故(undef / 無限ループ)は SSOT へ固定済み:
|
||||
- latch 記録は `TailCallKind::BackEdge` のみ
|
||||
- entry-like は “JoinIR main の entry block のみ”
|
||||
- 二重 latch は `debug_assert!` で fail-fast
|
||||
- 入口: `docs/development/current/main/phases/phase-188.3/P2-REFACTORING-INSTRUCTIONS.md`
|
||||
|
||||
---
|
||||
|
||||
## でかいファイルの棚卸し(再現コマンド)
|
||||
|
||||
```bash
|
||||
find src -name '*.rs' -print0 | xargs -0 wc -l | sort -nr | head -50
|
||||
```
|
||||
|
||||
このセッションの観測(500行超え):
|
||||
- 16 個
|
||||
|
||||
---
|
||||
|
||||
## 優先順位(今すぐやる価値)
|
||||
|
||||
### 1) `merge/mod.rs`(1,555行)— 最優先
|
||||
|
||||
現状: merge coordinator + value remap + 契約検証 + header PHI 構築が 1 ファイルに同居。
|
||||
方針: “純粋寄り” から剥がして、`mod.rs` は orchestrator に寄せる。
|
||||
|
||||
実行用の詳細プラン:
|
||||
- `docs/development/current/main/phases/phase-287/P0-MERGE_MOD_MODULARIZATION_PLAN.md`
|
||||
|
||||
#### 目標構造(案)
|
||||
|
||||
```
|
||||
src/mir/builder/control_flow/joinir/merge/
|
||||
├── mod.rs # orchestrator(公開APIと配線のみ)
|
||||
├── entry_selector.rs # loop header / entry block 選定(SSOT)
|
||||
├── header_phi_prebuild.rs # LoopHeaderPhiBuilder 呼び出し(SSOT)
|
||||
├── boundary_logging.rs # verbose/debug のみ(trace統一)
|
||||
└── verification/ # “契約検証” をまとめる
|
||||
├── mod.rs
|
||||
└── ... (既存 contract_checks.rs を移す/薄くする)
|
||||
```
|
||||
|
||||
#### SSOT(ここで削る推定)
|
||||
|
||||
- loop header の推定を boundary に寄せる:
|
||||
- `JoinInlineBoundary.loop_header_func_name` を優先し、無い場合のみ legacy heuristic
|
||||
- “log を常時出す” を禁止し、`trace.stderr_if(..., debug/verbose)` に統一
|
||||
|
||||
#### 受け入れ基準
|
||||
|
||||
- `cargo build --release` が通る
|
||||
- `./tools/smokes/v2/run.sh --profile quick` が PASS
|
||||
- 差分は “移動 + 入口統一” に限定(意味論不変)
|
||||
|
||||
---
|
||||
|
||||
### 2) `merge/instruction_rewriter.rs`(1,297行)— 今は“触らない”が正しい
|
||||
|
||||
現状: Scan → Plan → Apply の 3 段パイプラインが 1 ファイルで、局所的に複雑。
|
||||
方針: **Pattern6 の直後なので、いま大きく動かさない**(回帰コストが高い)。
|
||||
|
||||
#### ただし“安全にできる”こと(意味論不変)
|
||||
|
||||
- policy を 1 箇所へ集約して SSOT にする(既に一部完了)
|
||||
- latch 記録: `src/mir/builder/control_flow/joinir/merge/rewriter/latch_incoming_recorder.rs`
|
||||
- tail-call 分類: `src/mir/builder/control_flow/joinir/merge/tail_call_classifier.rs`
|
||||
- “loop header 推定” を boundary SSOT に寄せる(既に実装済み)
|
||||
|
||||
#### 将来の分割計画(今すぐはやらない)
|
||||
|
||||
- `scanner.rs` / `planner/` / `applicator.rs` へ物理分割
|
||||
- `RewriteContext` を SSOT にして、stage 間の引数を減らす
|
||||
|
||||
---
|
||||
|
||||
### 3) `patterns/ast_feature_extractor.rs`(1,148行)— 低難易度で効く
|
||||
|
||||
現状: 複数の “検出器” が同居。純粋関数なので物理分割が安全。
|
||||
方針: `pattern_recognizers/` を作って“1 recognizer = 1 質問”にする。
|
||||
|
||||
#### 目標構造(案)
|
||||
|
||||
```
|
||||
src/mir/builder/control_flow/joinir/patterns/
|
||||
├── ast_feature_extractor.rs # facade(re-export と glue)
|
||||
└── pattern_recognizers/
|
||||
├── mod.rs
|
||||
├── continue_break.rs
|
||||
├── infinite_loop.rs
|
||||
├── if_else_phi.rs
|
||||
├── carrier_count.rs
|
||||
└── ...(既存の extracted recognizer と揃える)
|
||||
```
|
||||
|
||||
#### 受け入れ基準
|
||||
|
||||
- 既存の public 関数シグネチャを維持(呼び出し側の差分を最小化)
|
||||
- `cargo build --release` + quick PASS
|
||||
- unit tests は “薄く” で良い(recognizer 単位で 1–2 個)
|
||||
|
||||
---
|
||||
|
||||
## 小テスト(1本だけ)で契約を固定する(推奨)
|
||||
|
||||
“bb番号や ValueId の固定” は不安定なので、**構造テスト**で固定する。
|
||||
|
||||
- latch 二重セット検知(debug): `LoopHeaderPhiInfo::set_latch_incoming()` に `#[should_panic]`
|
||||
- tail-call 分類の境界: `classify_tail_call()` の “entry-like でも target!=loop_step は LoopEntry ではない”
|
||||
|
||||
(MIR文字列の grep 固定は、ブロック番号が揺れやすいので最終手段)
|
||||
|
||||
---
|
||||
|
||||
## 検証手順(毎回)
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako # RC=9
|
||||
./tools/smokes/v2/run.sh --profile quick
|
||||
```
|
||||
@ -0,0 +1,123 @@
|
||||
# Phase 287 P0: `merge/mod.rs` Modularization Plan(意味論不変)
|
||||
|
||||
**Date**: 2025-12-27
|
||||
**Status**: Planning Complete(Ready for Implementation)
|
||||
**Parent**: Phase 287 (Big Files Refactoring)
|
||||
**Goal**: `src/mir/builder/control_flow/joinir/merge/mod.rs` を“配線だけ”に寄せる(意味論不変)
|
||||
|
||||
---
|
||||
|
||||
## 前提(直近の SSOT)
|
||||
|
||||
- Pattern6 の merge/latch 事故は SSOT 化済み
|
||||
- latch 記録は `TailCallKind::BackEdge` のみ
|
||||
- entry-like は “JoinIR main の entry block のみ”
|
||||
- 二重 latch は `debug_assert!` で fail-fast
|
||||
- loop header 推定は boundary SSOT を優先できる状態
|
||||
- `JoinInlineBoundary.loop_header_func_name`(明示)
|
||||
- ない場合のみ legacy heuristic(後方互換)
|
||||
|
||||
---
|
||||
|
||||
## 現状の問題
|
||||
|
||||
- `src/mir/builder/control_flow/joinir/merge/mod.rs` が巨大(責務が混在)
|
||||
- orchestrator / header PHI 構築 / entry 選定 / 値 remap / boundary ログ / 契約検証
|
||||
- “推定(heuristics)” と “契約(SSOT)” が混ざると回帰が起きやすい
|
||||
|
||||
---
|
||||
|
||||
## 目標(Target State)
|
||||
|
||||
- `merge/mod.rs` は orchestrator のみ(公開 API + 配線)
|
||||
- 純粋/半純粋ロジックを局所モジュールへ退避
|
||||
- SSOT: `boundary.loop_header_func_name` 優先、fallback は “互換のためだけ”
|
||||
- 意味論不変(挙動変更なし、silent fallback 追加なし)
|
||||
|
||||
---
|
||||
|
||||
## 提案ディレクトリ構造(案)
|
||||
|
||||
```
|
||||
src/mir/builder/control_flow/joinir/merge/
|
||||
├── mod.rs # orchestrator only
|
||||
├── entry_selector.rs # loop header func 選定(SSOT)
|
||||
├── header_phi_prebuild.rs # header PHI の事前構築(配線)
|
||||
├── value_remapper.rs # 小さな pure helper(必要なら)
|
||||
├── boundary_logging.rs # trace 統一(debug/verbose のみ)
|
||||
└── verification/
|
||||
├── mod.rs
|
||||
├── phi_dst_checks.rs
|
||||
├── carrier_checks.rs
|
||||
└── value_usage_checks.rs
|
||||
```
|
||||
|
||||
注:
|
||||
- “verification の SSOT” は既存 `merge/contract_checks.rs` と重なるので、移設するなら **入口を `verification/mod.rs` に統合**し、旧名は re-export で互換維持するのが安全。
|
||||
|
||||
---
|
||||
|
||||
## 実装フェーズ(Bottom-Up)
|
||||
|
||||
### Phase 1: `verification/` の抽出(低リスク)
|
||||
|
||||
- 対象: **pure function**(builder への副作用なし)だけを移す
|
||||
- 既存 `contract_checks.rs` と役割衝突しないように、移設後も呼び出し点の責務を増やさない
|
||||
|
||||
検証:
|
||||
- `cargo build --release`
|
||||
- `./tools/smokes/v2/run.sh --profile quick`
|
||||
|
||||
### Phase 2: 小さな helper の抽出(低リスク)
|
||||
|
||||
- `value_remapper.rs` は “本当に重複があるなら” に限定(作りすぎない)
|
||||
- 入口は `mod.rs` からのみ呼ぶ(依存拡散を避ける)
|
||||
|
||||
### Phase 3: `entry_selector.rs`(中リスク / SSOT)
|
||||
|
||||
SSOT:
|
||||
1) `boundary.loop_header_func_name` があればそれを使う
|
||||
2) なければ legacy heuristic(`MAIN` と `boundary.continuation_func_ids` を除外して最初の関数)
|
||||
|
||||
注意(重要):
|
||||
- “k_exit の名前一致” で除外するのは NG(continuation は SSOT が `boundary.continuation_func_ids`)
|
||||
- 対象は JoinIR function ではなく、merge が扱っている `MirModule.functions: BTreeMap<String, MirFunction>` の世界観に合わせる
|
||||
|
||||
検証:
|
||||
- fixture: `./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako`(RC=9)
|
||||
- quick: `./tools/smokes/v2/run.sh --profile quick`
|
||||
|
||||
### Phase 4: `header_phi_prebuild.rs`(中リスク)
|
||||
|
||||
- ここは “pure” ではなく “配線(orchestrator補助)” と割り切る
|
||||
- 入口で必要なもの(remapper / builder / boundary / loop_header_func_name など)を明示引数で受ける
|
||||
|
||||
### Phase 5: `boundary_logging.rs`(低リスク)
|
||||
|
||||
- `trace.stderr_if(..., debug/verbose)` へ統一
|
||||
- “常時ログ” を禁止(quick のノイズ増加は避ける)
|
||||
|
||||
### Phase 6: `merge/mod.rs` の最終整理(低リスク)
|
||||
|
||||
- 公開 API と “段取り” だけ残す
|
||||
- 変更は “移動 + 入口統一” に限定
|
||||
|
||||
---
|
||||
|
||||
## 検証(毎フェーズ)
|
||||
|
||||
```bash
|
||||
cargo build --release
|
||||
./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako # RC=9
|
||||
./tools/smokes/v2/run.sh --profile quick
|
||||
```
|
||||
|
||||
注:
|
||||
- “0 warnings” は現状リポジトリ特性として非現実的なので、**0 errors** と **新規の恒常ログ無し** を受け入れ条件にする。
|
||||
|
||||
---
|
||||
|
||||
## リスクメモ
|
||||
|
||||
- `merge/mod.rs` と `merge/instruction_rewriter.rs` は両方で “entry 選定” を持ちがちなので、SSOT を二重にしない(可能なら selector を共用、ただし大きく動かさない)。
|
||||
|
||||
Reference in New Issue
Block a user