Files
hakorune/docs/development/current/main/phases/phase-287/P0-BIGFILES-REFACTORING-INSTRUCTIONS.md
tomoaki 433e1d45c0 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>
2025-12-27 10:10:59 +09:00

5.0 KiB
Raw Blame History

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

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

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

目標構造(案)

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.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 質問”にする。

目標構造(案)

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