Files
hakorune/docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md
tomoaki fe895e8838 refactor(joinir): Phase 287 P2 - Modularize contract_checks (facade pattern)
- contract_checks.rs (846行) を facade 化
- 6モジュールへ分割(1 module = 1 contract):
  - terminator_targets.rs (208行) - Branch/Jump検証
  - exit_bindings.rs (35行) - exit_bindings ↔ exit_phis
  - carrier_inputs.rs (145行) - carrier_inputs完全性
  - boundary_creation.rs (160行) - B1/C2不変条件
  - entry_params.rs (317行) - Entry param一貫性
  - mod.rs (30行) - Facade
- Total: 846 → 895行(+49行モジュール境界オーバーヘッド)
- 意味論不変: エラータグ/ヒント文すべて保存
- Fail-Fast遵守: silent fallback追加なし
- 検証: Build 0 errors / Pattern6 RC=9 / quick 154/154 PASS

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-27 11:05:40 +09:00

5.7 KiB
Raw Blame History

Phase 287 P0: Big Files Refactoring 指示書(意味論不変 / 推定の削減)

Date: 2025-12-27
Status: Complete
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

でかいファイルの棚卸し(再現コマンド)

find src -name '*.rs' -print0 | xargs -0 wc -l | sort -nr | head -50

このセッションの観測500行超え:

  • 16 個

優先順位(今すぐやる価値)

1) merge/mod.rs1,555行— 最優先

現状: merge coordinator + value remap + 契約検証 + header PHI 構築が 1 ファイルに同居。
方針: “純粋寄り” から剥がして、mod.rs は orchestrator に寄せる。

実行用の詳細プラン:

  • docs/development/current/main/phases/phase-287/P0-MERGE_MOD_MODULARIZATION_PLAN.md

結果(実装済み):

  • merge/mod.rs: 1,555 → 1,053 lines
  • 新規モジュール: entry_selector.rs, header_phi_prebuild.rs, value_remapper.rs, boundary_logging.rs
  • heuristic 排除: continuation 判定は boundary.continuation_func_ids を SSOT に採用(文字列一致を撤去)

目標構造(案)

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統一
└── debug_assertions.rs         # merge 内の fail-fast / 契約検証debug で固定)

注:

  • Phase 287 P0 では verification/ の新設ではなく、既存の “契約検証” を debug_assertions.rs に統合した(意味論不変)。
  • P2contract_checks.rs を facade 化し、契約単位のモジュール分割を行う(contract_checks/ を新設予定)。

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.rs1,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.rs1,148行— 低難易度で効く

現状: 複数の “検出器” が同居。純粋関数なので物理分割が安全。
方針: pattern_recognizers/ を作って“1 recognizer = 1 質問”にする。

結果(実装済み):

  • ast_feature_extractor.rs: 1,148 → 135 linesfacade
  • pattern_recognizers/: 8 modules1 module = 1 質問)

目標構造(案)

src/mir/builder/control_flow/joinir/patterns/
├── ast_feature_extractor.rs          # facadere-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 単位で 12 個)

小テスト1本だけで契約を固定する推奨

“bb番号や ValueId の固定” は不安定なので、構造テストで固定する。

  • latch 二重セット検知debug: LoopHeaderPhiInfo::set_latch_incoming()#[should_panic]
  • tail-call 分類の境界: classify_tail_call() の “entry-like でも target!=loop_step は LoopEntry ではない”

MIR文字列の grep 固定は、ブロック番号が揺れやすいので最終手段)


検証手順(毎回)

cargo build --release
./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako   # RC=9
./tools/smokes/v2/run.sh --profile quick