Files
hakorune/docs/development/current/main/phases/phase-285/README.md
tomoaki b7f14e38d7 docs(lifecycle): Phase 285 P1 - Box lifecycle 実装棚卸し完了
## Rust VM 実装棚卸し(11項目)
- WeakBox 生成/観測/真実値判定: value.rs
- weak_to_strong: upgrade_weak() 失敗時 Void
- Finalizer: finalization.rs (scope レベル、InstanceBox 限定)
- Scope 追跡: scope_tracker.rs (Arc/Weak 管理)
- MIR WeakNew/WeakLoad: handlers/weak.rs

## LLVM harness 状況
- WeakNew/WeakLoad:  実装済み (llvm_py/instructions/weak.py)
- Finalizer:  未実装 (scope 管理なし)
- GC:  未実装 (RC のみ)

## P2 smoke 候補絞り込み(4本)
- weak_basic_vm/llvm: 既存+LLVM版
- weak_to_strong_fail: null 確認(新規)
- weak_cycle_report: leak report(新規)

**重要な発見**:
- WeakRef は両バックエンド完全実装(仕様通り)
- Finalizer は VM scope レベルで実装あり、LLVM 未対応

quick smoke 154/154 PASS

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

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-26 10:55:33 +09:00

14 KiB
Raw Blame History

Phase 285: Box lifecycle / weakref / finalization / GC conformance

Status: P0 COMPLETE (2025-12-26); A1 series + LLVM sub-phases implemented

Next (P0 docs-only → P1/P2)

  • P0 手順書: docs/development/current/main/phases/phase-285/P0-INSTRUCTIONS.md
  • 言語レベルSSOT:
    • lifecycle/weak/fini/GC: docs/reference/language/lifecycle.md
    • null/void/truthiness: docs/reference/language/types.md

LLVM Sub-Phases Status

Phase Status Summary
285LLVM-0.3 COMPLETE Leak report smoke test修正検証スコープ明確化 (2025-12-25)
285LLVM-1.1 COMPLETE ユーザーBox登録・デバッグ出力 (2025-12-24)
285LLVM-1.2 COMPLETE WeakRef基本動作identity保留 (2025-12-24)
285LLVM-1.3 COMPLETE InstanceBox Field Access (getField/setField) (2025-12-24)
285LLVM-1.4 COMPLETE print Handle Resolution (型タグ伝播) (2025-12-24)
285W-Syntax-0 COMPLETE weak文法SSOT確定 (weak x unary operator) (2025-12-24)
285W-Syntax-0.1 COMPLETE weak(x) 完全拒否 (Parser-level Fail-Fast) (2025-12-24)

LLVM Details: See phase-285llvm-1.3-verification-report.md Syntax Change: Phase 285W-Syntax-0 migrates from weak(x) function call to weak x unary operator Syntax Enforcement: Phase 285W-Syntax-0.1 enforces parser-level rejection of weak(...) syntax with helpful error message

Phase 285LLVM-0.3 (2025-12-25): Smoke test 修正

  • NYASH_DISABLE_PLUGINS=1 削除、plugins 有効化で leak report 動作確認
  • stdout 検証を削除leak report のみを検証対象とする)
  • 結果: 45/46 PASS退行なし
  • コメント修正: 「print() は機能しない」→「このsmoke testはleak reportingのみ検証」SSOT整合

Goal

Box の生存期間(強参照/弱参照/解放/最終化/GCを SSOT として固定し、移行期間でも意味論が割れない状態にする。

Language-level SSOT:

  • Lifecycle/weak/fini/GC policy: docs/reference/language/lifecycle.md
  • Truthiness + null/void: docs/reference/language/types.md

This Phase document is not the language SSOT; it tracks implementation status, backend gaps, and acceptance criteria.

Implemented (A1 series)

See docs/development/current/main/phases/phase-285/phase-285a1-boxification.md.

  • WeakRef E2E (VM/LLVM harness): weak <expr> + weak_to_strong(), plus strict weak-field contract (no implicit weakification).
  • Visibility support: public { weak parent } plus sugar public weak parent (same meaning).
  • Parser robustness: parameter type annotations (arg: Type) are rejected with a clear parse error (no hang).
    • Helper: src/parser/common/params.rs
    • Smoke: tools/smokes/v2/profiles/quick/parser/phase285_param_type_annotation_nohang.sh

Why now

  • JoinIR/Plan/compose の収束が進むほど、実行時の “値の寿命” の揺れが目立つ。
  • weakref/finalization は「実装が仕様」になりやすく、後から直すコストが最大級。
  • LLVM harness 側は未対応の可能性が高く、差分を “仕様として明文化” しないと再現/調査が難しい。

SSOT References (current code)

  • weakref の値表現: src/value.rsNyashValue::WeakBox
  • finalization: src/finalization.rs
  • Box trait: src/box_trait.rsSharedNyashBox = Arc<dyn NyashBox>
  • Scope tracking: src/scope_tracker.rsBox の登録/スコープ)

Snapshot今わかっていること

  • weakref は Weak<Mutex<dyn NyashBox>> で保持される(NyashValue::WeakBox
  • WeakBoxto_string()weak_to_strong() を試み、WeakRef(null) 表示になりうる(観測可能)
  • src/value.rs に weakref の drop 挙動を固定する unit test がある(test_weak_reference_drop

Responsibility Mapどこが仕様を決めるか

  • SSOT意味: docs/reference/language/*言語レベルのSSOT
  • Conformance: Rust VM / LLVM harness / WASM / JIT など各バックエンド実装
  • 観測の固定: fixture/smokePhase 285 P2 で作る)

用語P0で固定する

  • Strong reference: 所有参照(Arc 等で Box を保持)
  • Weak reference: 非所有参照(Weak / weak_to_strong() が失敗しうる)
  • Weak-to-strong: weak → strong の昇格(成功/失敗が意味論)
  • Roots: 解放/GC から保護される参照集合stack/local/global/handle/plugin
  • Finalizer: 解放に伴う最終化処理(もし存在するなら)

P0 decisions (docs-only) COMPLETE (2025-12-26)

言語 SSOT との境界

関心事 SSOT Phase 285 での扱い
Lifecycle/weak/fini docs/reference/language/lifecycle.md 実装状況・差分追跡のみ
null/void/truthiness docs/reference/language/types.md 実装状況・差分追跡のみ
VM/LLVM 差分 このファイル 「未対応/既知バグ/保留」として分類

原則: Phase 285 は言語 SSOT を書き換えない。実装の棚卸しと差分追跡を行う。

用語(固定)

用語 定義
Roots 解放/GC から保護される参照集合stack/local/global/handle/plugin
Strong reference 所有参照(Arc 等で Box を保持、解放を遅延)
Weak reference 非所有参照(Weak / weak_to_strong() が失敗しうる)
Weak-to-strong weak → strong の昇格(成功/失敗が意味論、失敗時は null
Finalizer (fini) 解放に伴う論理的終了処理(物理解放とは別)
Collection (GC) 到達不能オブジェクトの回収(意味論ではなく補助)

禁止事項

禁止事項 理由
Finalizer 内での再入 デッドロック/無限再帰のリスク
Finalizer 内での例外送出 終了処理の信頼性を損なう
Finalizer 内での allocation GC サイクル中の新規割当は危険
Silent fallback黙殺 未対応は Err または理由付き SKIP で固定
新しい環境変数トグル 既存の診断導線の範囲で対応

VM/LLVM 差分分類

機能 VM (Rust) LLVM harness 分類
weak <expr> 実装済み 実装済み (A) 仕様通り
weak_to_strong() 実装済み 実装済み (A) 仕様通り
Weak field contract 実装済み 実装済み (A) 仕様通り
Finalizer (fini) ⚠️ 未実装 ⚠️ 未実装 (B) 未実装
GC (cycle collection) ⚠️ RC のみ ⚠️ RC のみ (B) 未実装
Exit-time leak report 診断あり 診断あり (A) 仕様通り

分類凡例:

  • (A) 仕様通り: VM/LLVM 両方で動作
  • (B) 未実装: 言語仕様にあるが実装されていない
  • (C) 既知バグ: 実装はあるが動作が仕様と異なる
  • (D) 仕様外: 禁止されている

Core decisions

  • Weak の観測は weak_to_strong() で行い、失敗値は null= runtime Void の別名)。
  • cleanupStage3 block-postfixが「出口で必ず走る」決定的 cleanup を保証する(catch の有無に関係なく、常に実行)。
  • GC は意味論ではなく補助GC off で cycle はリークしうる)。
  • ByRef (RefGet/RefSet) は non-owning / non-escaping寿命・弱参照・GC の道具にしない)。

RUNBOOK caveat (implementation reality)

The runbook assumes WeakRef infrastructure exists in the VM and lowering. If any of the following are missing, treat weak smokes as unsupported and scope to exit-time leak report first:

  • weak <expr> parse/lower (and weak(...) is rejected)
  • VM handler for MIR WeakRef/WeakNew/WeakLoad
  • language-surface weak_to_strong() on WeakRef

Questions to Answer (P0/P1)

  • weakref の “生存判定” は何で観測できるか(toString / is_alive / weak_to_strong API など)
  • finalizer は存在するか / いつ発火するかdrop 時GC 時?明示 API
  • finalizer 内での禁止事項再入、例外、I/O、allocationをどうするか
  • LLVM harness の扱い(現状未対応なら “未対応として SSOT 化”)

Scope (proposed)

P0docs-only

  • 用語の固定strong/weak/roots/finalizer/collection
  • 仕様の固定weakref の weak_to_strong 成否、finalizer の発火条件、禁止事項)
  • “LLVM harness の扱い” を明文化(未対応なら未対応として SSOT に書く)

P1investigation COMPLETE (2025-12-26)

目的: Rust VM の現状実装の棚卸し(どこで roots が形成され、どこで解放/最終化されるか)

Rust VM 実装棚卸し

責務 ファイル 関連シンボル 観測ポイント SSOT との差分
WeakBox 生成 src/value.rs:32 NyashValue::WeakBox Weak<Mutex<dyn NyashBox>> で保持 仕様通り
weak_to_strong src/value.rs:196-201 upgrade_weak() Weak::upgrade() 失敗時 Void 仕様通り
WeakBox 観測 src/value.rs:106-115 to_string() + upgrade() WeakRef(null) 表示で死亡観測可能 仕様通り
WeakBox 真実値 src/value.rs:157-160 to_bool() weak_ref.upgrade().is_some() → 生死判定 仕様通り
Finalizer 登録 src/finalization.rs:49-52 BoxFinalizer::track() InstanceBox のスコープ終了時 fini() 呼び出し ⚠️ スコープレベル
Finalizer 呼び出し src/finalization.rs:61-76 finalize_all() instance.fini() を呼び出す(存在チェック付き) 実装済み
Scope 追跡 src/scope_tracker.rs:14-28 ScopeTracker stack: Vec<Vec<Arc<dyn NyashBox>>> 実装済み
Scope push/pop src/scope_tracker.rs:31-43 push_scope()/pop_scope() 逆順で fini() 呼び出し 実装済み
Roots 形成 src/scope_tracker.rs:85-100 enter_root_region()/leave_root_region() GC root region 管理Phase 10.4 prep ⚠️ 準備中
MIR WeakNew src/backend/mir_interpreter/handlers/weak.rs:23-34 handle_weak_new() Box → Weak の変換 仕様通り
MIR WeakLoad src/backend/mir_interpreter/handlers/weak.rs:48-58 handle_weak_load() Weak → Box | Void 昇格 仕様通り

重要な観測:

  • ScopeTrackerRust MM レベルArc/Weakで管理
  • BoxFinalizerスコープレベル(ブロックスコープ)で管理(別モジュール)
  • WeakRef は 値表現レベル (Weak<Mutex<dyn NyashBox>>) で実装
  • Finalizer は InstanceBox 限定downcast_ref::<InstanceBox>() で確認後呼び出し)

LLVM harness 状況

機能 実装状況 ファイル 備考
WeakNew 実装済み src/llvm_py/instructions/weak.py:12-61 @nyrt_weak_new() 呼び出し
WeakLoad 実装済み src/llvm_py/instructions/weak.py:63-112 @nyrt_weak_to_strong() 呼び出し
Finalizer (fini()) 未実装 - 対応関数なし
GC / Cycle Collection 未実装 - Reference Count のみ

重要な発見:

  • (A) 仕様通り: weak <expr> + weak_to_strong()両バックエンド で動作
  • (B) 未実装: Finalizer (fini()) は 両バックエンド で言語意味論としては統一されていない
    • VM: scope_tracker.rspop_scope() 時に InstanceBox .fini() を呼び出し(実装あり)
    • LLVM: 対応する finalizer 呼び出し機構がない(現在 harness は scope 管理を持たない)

P2smoke

目的: weakref の最小 fixture/smoke を作り、挙動を固定する

P2 smoke 候補(絞り込み済み)

smoke 内容 期待値 優先度
phase285_weak_basic_vm.sh 既存 weak basic smokeweak x + weak_to_strong() 成功) PASS既に存在 既存
phase285_weak_to_strong_fail_vm.sh weak_to_strong 失敗観測Void = null PASSWeakRef(null) または void 確認) 新規
phase285_weak_cycle_report_vm.sh 強参照サイクルで leak report PASSexit-time leak report で検出) 新規
phase285_weak_basic_llvm.sh LLVM weak 基本動作確認 PASSVM と同一動作) 新規

LLVM 扱い:

  • WeakNew/WeakLoad は 両バックエンド実装済み → smoke は --backend vm--backend llvm 両方実行
  • Finalizer は 両バックエンド未実装P2 では scope finalization のテストを行わない
  • 未対応機能: 理由付き SKIPtest_skip "reason"
  • silent fallback 禁止

P2 で扱わない項目:

  • Finalizer (fini()) の統一テスト → Phase 286+ で統一化予定
  • GC cycle collection → Reference Count のみで既知の制約

Non-goals

  • GC アルゴリズム刷新RC→tracing 等の設計変更)
  • LLVM harness に同等機能を “一気に” 実装(差分の記録→段階導入を優先)

Acceptance criteria (P2+)

  • VM と LLVM で、weak が仕様通り動作する(weak_to_strong() 成功/失敗が一致、失敗は null)。
  • 強参照サイクルを意図的に作ったとき、GC off なら)回収されないことが観測できる。
  • 終了時に「強参照が残っている root」をデバッグ出力できるdefault-off の診断フラグ)。
    • これは意味論ではなく診断であり、ON/OFF でプログラムの意味を変えない。