Struct / Encoding coverage audit
2026-05-23生成 — post-c9a535aのrigor-type-coverage-upliftラインのPhase 5成果物。Phase 5のスコープは「残りの低優先度キャリア」であった。両型に対するauditの結論は決定であり、dispatchスライスではない。一方はADR化に値する機能として延期され、もう一方は恒久的な対象外として推奨される。
1. Struct — 延期(struct-shapeキャリアが必要;ADR化に値する)
Section titled “1. Struct — 延期(struct-shapeキャリアが必要;ADR化に値する)”Struct.new(*members)は新しい匿名サブクラスを返す。STRUCT_CATALOGは防衛的な設計になっている(struct_catalog.rbを参照):Structをレシーバークラスとして認識し、Struct.newをオプションのクラスボディブロックに対して:block_dependentに分類し、「仮想的な将来のConstant<Struct>キャリア」に対して:[] / :hash / :initialize_copyをブロックリスト登録済みとしている。
spec/integration/fixtures/struct_catalog.rbは現状を固定している:
klass = Struct.new(:foo, :bar) # => Nominal[Struct]inst = Struct.new(:foo).new(1) # => Dynamic[top]inst.fooは畳み込みできない。サブクラスごとのメンバーレイアウトをモデル化するものが存在しないためである。
coverage-upliftスライスではない理由
Section titled “coverage-upliftスライスではない理由”Structメンバーへの精密なアクセス(Point = Struct.new(:x, :y); p = Point.new(1, 2); p.x # Constant[1])には、dispatchティアへのエントリーではなく、2つの新しいキャリアが必要である:
- struct-classキャリア — 順序付きメンバー名リスト(および
keyword_init:フラグ)でパラメータ化された匿名Structサブクラス。 - struct-instanceキャリア — メンバー名→値の型のマッピング。本質的にクラスタグを持つ
HashShapeであり、.x/.x=/[]/to_h/deconstructが精密に射影される。
これは本物の機能であり、実際の設計上の問題を含んでいる。そのいずれもcoverage-upliftコーパスでは決定されていない:
Struct.newのクラスボディブロック(do … end)は追加のメソッドを定義できる — キャリアはそれが発生した場合に安全にデグレードしなければならない;keyword_init: trueの構造体、位置引数版Struct、およびRuby 3.2のハイブリッド;- structのサブクラス(
class Point3D < Point); - イミュータブルな兄弟型
Data.define(Ruby 3.2以降) —Dataインスタンスはfrozenであるため、キャリアの健全性の議論がより単純になり、Structよりも適切な最初のターゲットとも言える。
Struct / Dataの値の畳み込みは、自律的なcoverageスライスではなく、専用のADRを持つ独立した機能(キャリア群への追加 + Struct.new / Data.defineのブロックデグレード契約)として扱うこと。HashShapeキャリアは明らかな構造的先例である。このauditによる実装は認可されていない。
2. Encoding — 恒久的な対象外として推奨
Section titled “2. Encoding — 恒久的な対象外として推奨”ENCODING_CATALOGはSTRUCT_CATALOGと同じ形で防衛的な設計になっている:Encodingは認識済みのレシーバーであり、RBSティアはNominal[Encoding]を返し、レジストリを走査するシングルトン(Encoding.find / .list / .aliases / .name_list)およびミューテーティングセッター(default_external= / default_internal=)はプロセスレジストリ依存としてブロックリスト登録済みである。
キャリアがコストに見合わない理由
Section titled “キャリアがコストに見合わない理由”Constant[Encoding]キャリアが畳み込めるのは、ごくわずかな表面に限られる:
Encoding::UTF_8.name→Constant["UTF-8"]、.dummy?→Constant[false]、.ascii_compatible?→Constant[true]。
実際のプログラムはEncodingオブジェクトに対して静的計算を行わない — この型はString#encode / #force_encodingに渡される不透明なタグとして使用される。ブロックリスト登録済みのレジストリメソッド(興味深い戻り値を持つ唯一のもの)は、その答えがアナライザープロセスに依存するため、ブロックリスト登録済みのままとなる。既存のNominal[Encoding]の答えに対する精度向上は無視できる程度であり、新しいSCALAR_CLASSESのメンバーを追加するたびにキャリア群が拡大される(Ractorの共有可能性、describe、erase_to_rbs、== / hash契約)が、ユーザーへの利益はない。
Encoding定数キャリアを追加しないこと。現在のNominal[Encoding]の答えは正確かつ十分であり、ENCODING_CATALOGの防衛的なブロックリストはすでに健全でないパスをカバーしている。これは意図的な恒久的な対象外であり、問題が再議論されないよう記録する。
3. Phase 5 outcome
Section titled “3. Phase 5 outcome”| 型 | 判断 | 理由 |
|---|---|---|
| Struct / Data | 延期(ADR化推奨) | struct-shapeキャリア2種が前提。実機能でありcoverageスライスではない。 |
| Encoding | 恒久的に対象外 | キャリア新設のコストに見合う精度向上がない。Nominal[Encoding]で十分。 |
coverage-upliftラインのPhases 1–4はdispatch / carrierスライスとして着地した。Phase 5は、残りの2つの候補がそれぞれ延期された機能と恒久的な対象外であることを記録することで、このラインを締めくくる。
© 2026 TypedDuck. Licensed under CC BY-SA 4.0.