Files
hakorune/docs/phases/phase-9/phase_9_75c_debugbox_fix.md

10 KiB
Raw Blame History

Phase 9.75-C DebugBox修正: 残存する39個のコンパイルエラー解決

優先度: 🔴 緊急 (全開発ブロック中) 担当者: @copilot-swe-agent
ステータス: 未解決 作成日: 2025-08-15 関連: Issue #92 (解決済み), PR #93 (FutureBox修正完了)

🚨 問題概要

Issue #92とPR #93でFutureBox問題は解決済みですが、DebugBoxのArc→RwLock変換が完全に見落とされており、39個のコンパイルエラーが残存しています。

現在の状況

$ cargo check --lib
error: could not compile `nyash-rust` (lib) due to 39 previous errors; 80 warnings emitted

影響: 全開発がブロック - ビルド、テスト、Phase 9.5以降の作業継続不可

📋 現在の状況

解決済み問題 (Issue #92 / PR #93)

  • FutureBox二重定義: 完全解決
  • 10個のBox型: HTTPServerBox、P2PBox等はRwLock変換済み

未解決問題 (この新しいIssue)

  • DebugBox: Arc→RwLock変換が完全に見落とされている

変換済みBox型 (PR #91 + PR #93)

  • HTTPServerBox: 7個のArcフィールド → RwLock
  • P2PBox: Arc<Mutex<P2PBoxData>>型エイリアスから完全書き換え
  • IntentBox: Arc<Mutex<IntentBoxData>>型エイリアスから完全書き換え
  • SimpleIntentBox: listenersハッシュマップ変換
  • JSONBox: serde_json::Value操作
  • RandomBox: seedフィールド変換
  • EguiBox: クロススレッドArcでの複雑なGUI状態
  • FileBox: ファイルI/O操作、パス簡素化
  • FutureBox: 非同期状態管理 PR #93で解決
  • SocketBox: TCP操作更新

未変換Box型

  • DebugBox: 完全に見落とされている

🔍 DebugBox問題の技術的分析

具体的エラー箇所: src/boxes/debug_box.rs

📊 特定されたエラー

1. DebugBox構造体: Clone derive問題

// ❌ 現在の問題
#[derive(Debug, Clone)]  // RwLockはCloneを実装していない
pub struct DebugBox {
    tracking_enabled: RwLock<bool>,
    tracked_boxes: RwLock<HashMap<String, TrackedBoxInfo>>,
    breakpoints: RwLock<Vec<String>>,
    call_stack: RwLock<Vec<CallInfo>>,
}

2. 11箇所の.lock()呼び出し: メソッド名エラー

src/boxes/debug_box.rs:182   instance.fields.lock().unwrap()
src/boxes/debug_box.rs:191   self.tracked_boxes.lock().unwrap()  
src/boxes/debug_box.rs:231   self.tracked_boxes.lock().unwrap()
src/boxes/debug_box.rs:251   self.breakpoints.lock().unwrap()
src/boxes/debug_box.rs:258   self.call_stack.lock().unwrap()
src/boxes/debug_box.rs:274   self.call_stack.lock().unwrap()
src/boxes/debug_box.rs:290   self.tracked_boxes.lock().unwrap()
src/boxes/debug_box.rs:293   self.call_stack.lock().unwrap()
src/boxes/debug_box.rs:306   self.tracked_boxes.lock().unwrap()
src/boxes/debug_box.rs:322   self.tracked_boxes.lock().unwrap()
src/boxes/debug_box.rs:345   self.tracked_boxes.lock().unwrap()

3. Clone実装: 手動実装が必要

RwLockはCloneを実装していないため、手動Clone実装が必要。

🎯 目標アーキテクチャ (達成すべき状態)

// ✅ 正しい: 単一責務設計
struct DebugBox {
    tracking_enabled: RwLock<bool>,      // シンプルな内部可変性
    tracked_boxes: RwLock<HashMap<String, TrackedBoxInfo>>,
    breakpoints: RwLock<Vec<String>>,
    call_stack: RwLock<Vec<CallInfo>>,
}
// 外部: Arc<Mutex<dyn NyashBox>> (変更なし)

// ❌ 間違い: 二重ロック問題 (排除済み)
struct DebugBox {
    field: Arc<Mutex<T>>,  // 内部ロック - 排除済み
}
// + 外部: Arc<Mutex<dyn NyashBox>>

🔍 修正すべきパターン

1. Clone derive削除 + 手動実装

// ❌ 削除すべき
#[derive(Debug, Clone)]

// ✅ 変更後
#[derive(Debug)]
pub struct DebugBox {
    // ... フィールド
}

impl NyashBox for DebugBox {
    fn clone_box(&self) -> Box<dyn NyashBox> {
        // 手動Clone実装PR #87パターン
        let tracking_enabled = *self.tracking_enabled.read().unwrap();
        let tracked_boxes = self.tracked_boxes.read().unwrap().clone();
        let breakpoints = self.breakpoints.read().unwrap().clone();
        let call_stack = self.call_stack.read().unwrap().clone();
        
        Box::new(DebugBox {
            base: BoxBase::new(),
            tracking_enabled: RwLock::new(tracking_enabled),
            tracked_boxes: RwLock::new(tracked_boxes),
            breakpoints: RwLock::new(breakpoints),
            call_stack: RwLock::new(call_stack),
        })
    }
}

2. RwLockパターンの体系的適用

読み取りアクセス:

// ❌ 変更前
let tracked = self.tracked_boxes.lock().unwrap();
let value = tracked.some_property;

// ✅ 変更後  
let tracked = self.tracked_boxes.read().unwrap();
let value = tracked.some_property;

書き込みアクセス:

// ❌ 変更前
let mut tracked = self.tracked_boxes.lock().unwrap();
tracked.insert(key, value);

// ✅ 変更後
let mut tracked = self.tracked_boxes.write().unwrap();
tracked.insert(key, value);

🎯 受け入れ基準 (ゴール)

主要目標: コンパイル成功

$ cargo check --lib
Finished `dev` profile [unoptimized + debuginfo] target(s) in X.XXs

副次目標: クリーンビルド

$ cargo build --release -j32  
Finished `release` profile [optimized] target(s) in X.XXs

検証: DebugBox機能確認

# DebugBox基本機能テスト
$ ./target/release/nyash test_debug_basic.nyash
✅ DebugBoxがRwLockで動作

# 追跡機能テスト
$ ./target/release/nyash test_debug_tracking.nyash  
✅ メモリ追跡・ブレークポイント機能正常

品質保証: パターンの一貫性

# DebugBoxでのArc<Mutex>排除確認
$ grep -r "Arc<Mutex<" src/boxes/debug_box.rs
# 結果: 0件であるべき

# DebugBoxでのRwLock採用確認
$ grep -r "RwLock<" src/boxes/debug_box.rs | wc -l  
# 結果: 4件 (tracking_enabled, tracked_boxes, breakpoints, call_stack)

🛠️ 詳細修正手順

ステップ1: Clone derive削除

// src/boxes/debug_box.rs: line 110
// ❌ 削除
#[derive(Debug, Clone)]

// ✅ 変更後
#[derive(Debug)]

ステップ2: 11箇所の.lock()変換

読み取り専用アクセス (8箇所):

// Lines: 191, 231, 274, 306, 322, 345
self.tracked_boxes.lock().unwrap()  self.tracked_boxes.read().unwrap()

// Line: 182 (別ファイルのinstance.fields)
instance.fields.lock().unwrap()  instance.fields.read().unwrap()

// Line: 274
self.call_stack.lock().unwrap()  self.call_stack.read().unwrap()

書き込みアクセス (3箇所):

// Lines: 251, 258, 290, 293
self.breakpoints.lock().unwrap()  self.breakpoints.write().unwrap()
self.call_stack.lock().unwrap()  self.call_stack.write().unwrap()
self.tracked_boxes.lock().unwrap()  self.tracked_boxes.write().unwrap()

ステップ3: 手動Clone実装

impl NyashBox for DebugBox {
    fn clone_box(&self) -> Box<dyn NyashBox> {
        // PR #87確立パターンに従う
        let tracking_enabled = *self.tracking_enabled.read().unwrap();
        let tracked_boxes = self.tracked_boxes.read().unwrap().clone();
        let breakpoints = self.breakpoints.read().unwrap().clone();
        let call_stack = self.call_stack.read().unwrap().clone();
        
        Box::new(DebugBox {
            base: BoxBase::new(), // 新しいユニークID
            tracking_enabled: RwLock::new(tracking_enabled),
            tracked_boxes: RwLock::new(tracked_boxes),
            breakpoints: RwLock::new(breakpoints),
            call_stack: RwLock::new(call_stack),
        })
    }
}

🧪 テスト要件

重要なテストケース

  1. DebugBox基本機能: startTracking, stopTracking, trackBox
  2. メモリレポート: memoryReport, dumpAll機能
  3. ブレークポイント: setBreakpoint, traceCall機能
  4. 並行アクセス: RwLockによる複数読み取り者対応

リグレッション防止

  • 既存のDebugBox機能は全て変更なく維持されること
  • Everything is Box哲学が保持されること
  • パフォーマンスが向上すること (RwLockは並行読み取り可能)

📚 参考資料

成功事例

  • PR #87: ArrayBox、MapBox、TimeBoxでRwLockパターンを確立
  • PR #93: FutureBox二重定義問題の解決例

アーキテクチャドキュメント

  • Everything is Box哲学: docs/説明書/reference/box-design/
  • RwLockパターン: PR #87で確立されたパターンに従う

関連Issue

  • Issue #92: FutureBox問題 (解決済み)
  • PR #93: FutureBox修正 (完了)

🚀 修正後の期待される影響

パフォーマンス向上

  • 並行読み取りアクセス: RwLockは複数読み取り者可能 vs Mutex単一アクセス
  • デバッグ効率化: メモリ追跡の並行処理対応
  • デッドロック防止: Arc二重ロックシナリオの完全排除

開発ブロック解除

  • Phase 9.5準備完了: 全Box型がHTTPサーバーテスト対応
  • WASM/AOT開発: 全Box型がコンパイル互換
  • デバッグ機能: 本格運用でのパフォーマンス監視可能
  • 将来のPhase: Phase 10+ LLVM作業の堅実な基盤

⚠️ 品質要件

これは最後の仕上げです - 以下を確実に:

  1. 完全なパターン適用: 全11箇所の.lock() → .read()/.write()変換
  2. 型安全性: Clone実装をRwLockに対応した手動実装で解決
  3. パフォーマンス検証: RwLock使用が読み取り/書き込みベストプラクティスに従うこと
  4. 機能保持: DebugBoxの全機能を完全に維持すること
  5. アーキテクチャ統一: 他10個のBox型と同じRwLockパターン適用

目標は、Everything is Box哲学を最適なパフォーマンスで完全に実現する 堅牢で本番レディな実装 です。


推定作業量: 1-2時間 (明確に特定された11箇所の修正) リスクレベル: 低 (問題箇所特定済み・修正パターン確立済み) 依存関係: 解決まで全Phase 9.5+開発をブロック 緊急度: 最高 (他の全Box型は変換完了、DebugBoxのみ残存)