Nyash 設計検討メモ（RFC）: 多重デリゲーション競合ポリシーと fini の意味づけ

最終更新: 2025-08-13

目的
- 多重デリゲーションにおける競合解決ポリシーを明文化し、実装・診断メッセージと揃える。
- fini（論理的解放フック）の意味論と期待管理を定義し、現状課題と解決策を整理する。

---

1) 多重デリゲーションの競合ポリシー（提案仕様）

基本方針
- 明示最優先: 解決順は定めない。曖昧さがある場合はエラーとし、明示（修飾/override）を要求する。
- 子の定義優先: 子で定義/overrideされたものが最優先される。

メソッド解決
- 子に同名メソッドがあればそれを使用。上書きは必ず `override` を要する。
- 子に無く、親のうち「ちょうど1つ」だけがメソッドを提供するなら自動選択。
- 親の「複数」が同名メソッドを提供する場合は曖昧エラー。
  - 対処: 子で `override foo(...) { return from A.foo(...); }` のように一本化、または呼び出しごとに `from A.foo(...)` / `from B.foo(...)` を使う。
- 親呼び出しは常に `from Parent.m(...)` で明示修飾できる（推奨パターン）。

フィールド解決
- 子がフィールドを持てばそれを使用。
- 子に無く、親のうち「ちょうど1つ」だけが同名フィールドを持つ場合は自動選択。
- 複数親が同名フィールドを持つ場合は曖昧エラー。
  - 対処: 子で別名のラッパー/アクセサを定義して再輸出、または（将来案として）`from Parent.field` の明示アクセスを利用。

インターフェース整合
- インターフェースが要求するメソッドに対し、複数親が候補を提供する場合、子は必ず `override` して一本化（または合成）する。

ビルトイン/Static Box
- 同一ポリシーを適用。曖昧な場合はエラーで明示を要求。

診断メッセージ例
- Method 'foo' is provided by: A, B. Disambiguate via:
  - override foo(...) { return from A.foo(...); }
  - or call with qualification: from A.foo(...)
- Field 'x' is provided by: A, B. Define an alias in child or qualify access.

実装の要点（簡易アルゴリズム）
- 解決時に候補集合 S を作成。|S|=0 → 未定義エラー。|S|=1 → その定義を使用。|S|>1 → 曖昧エラー。
- 子の定義は候補集合より常に優先（S を見る前に確定）。
- メソッド/フィールドで同一ロジックを共有できるようヘルパー化。

補助パターン（任意）
- 構文追加は避け、子側に明示ラッパーを定義して再輸出するのを推奨（後方互換/可読）。
- 拡張案として alias 機構（例: alias { A.foo -> aFoo }）は将来検討。

---

2) fini（論理的解放フック）の意味づけと期待管理

定義（言語仕様）
- `fini()` は「論理的解放」を宣言するフック。呼び出しコンテキストで当該インスタンスを以後使用しないことを示し、関連資源の解放を行う。
- 共有参照（他所の強参照）が残存していても、言語意味論上は finalized（使用不可）とみなす。実体メモリが残る場合があるのは実装都合。

使用禁止のガード
- `fini()` 後の操作はエラー（idempotent な `fini()` 再呼出しのみOK）。
- 対象: メソッド呼出し、フィールドアクセス、代入、デリゲーション経由の呼出し等。
- 推奨エラーメッセージ: "Instance was finalized; further use is prohibited"。

波及とクリーンアップ
- `fini()` は所有フィールドにも波及。子Boxであるフィールドに対し `fini()` を呼び、その後フィールドをクリア。
- 弱参照はアクセス時 upgrade 失敗で自動的に `null`（lazy nil化）。必要に応じてデバッグモードで eager 無効化（任意機能）。

現状課題（2025-08 時点）
- 内部 `instance.fini()` が、全フィールド再帰 `fini()` → クリア を必ずしも保証していない（実装強化余地）。
- `fini()` 後の使用禁止ガードが緩く、明確なエラー化が不十分なコードパスがある可能性。
- 共有参照が残るケースの意味論が docs に十分明示されておらず、誤解リスクがある。

解決策（優先度順）
1) 内部解放強化: `instance.fini()` 内で全フィールドを走査し、InstanceBox へは `fini()`、二重防止フラグ→最後にクリア。
2) ガード導入: `get_field`/`set_field`/`get_method` など入口で `finalized` チェック→使用禁止エラーを返す。
3) ドキュメント明記: fini = 論理的解放。共有参照残存時も以後の使用は禁止。弱参照はアクセス時 `null`。
4) 可視化: Playground に `fini` 回数/weak upgrade 失敗数/エラー例の表示を追加し、期待を合わせる。

禁止事項（weak への fini 呼び出し）
- ルール: `init { weak ... }` で宣言されたフィールドに対する `fini()` 直接呼び出しは禁止（非所有参照の解放に相当）。
- 診断方針: 可能な限りビルドエラーで検出し、動的経路は実行時エラーで防止。
- 推奨メッセージ: "Cannot finalize weak field '<name>' (non-owning reference). Set it to null or rely on lazy nilification."

備考（質問への回答）
- 「共有参照が残っていても解放が正しいか？」→ はい。言語意味論では“以後使用禁止”を宣言するのが `fini()` で、
  物理メモリが残るかどうかはランタイムの参照カウントに依存するだけ。禁止ガードと文書化で期待を一致させる。

---

3) 追補: 実装/ドキュメント TODO
- interpreter: 候補集合による曖昧検出と診断の実装（メソッド/フィールド）。
- instance: 再帰的 `fini()` + フィールドクリアの保証、finalized ガードの一元化。
- docs: LANGUAGE_GUIDE / reference に上記仕様を反映（サンプルと期待エラーメッセージ含む）。
- playground: メトリクス・エラーの可視化を追加（検証再現性の強化）。
