- 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>
5.0 KiB
5.0 KiB
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
- latch 記録は
でかいファイルの棚卸し(再現コマンド)
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
- latch 記録:
- “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 固定は、ブロック番号が揺れやすいので最終手段)
検証手順(毎回)
cargo build --release
./target/release/hakorune --backend vm apps/tests/phase1883_nested_minimal.hako # RC=9
./tools/smokes/v2/run.sh --profile quick