コンテンツにスキップ

概要

Rigorの型言語はRBSの厳密なスーパーセットです。

RBS → Rigor方向は無損失です。すべてのRBS型はRigor内に表現を持ち、それを通って同じRBS型に往復します。Dynamic[T](詳細はspecial-types.md)のような内部の精度を担うラッパーは境界で可逆であり、往復は近似ではなく完全に一致します。

Rigor → RBS方向は無損失ではありません。Rigorが推論したすべての型はRBSへの消去(erasure)を持っていなければならず、これによりRigorは近似を通常のRBSとしてエクスポートできます。消去はリファインメント、リテラルユニオン、シェイプ(shape)、動的由来(provenance)を潰すことが許されます。消去はRigorが証明した型より狭い型を生成してはならず、より広い型を生成することは許されます。

Rigorは相互運用面としてRBSを使い、推論・制御フロー解析・診断にはより豊かな内部型モデルを用います。

RigorはPHPStan、TypeScript、Pythonのtyping仕様からアイデアを借りますが、それらはRubyらしい形に整えられます:

  • RBSのクラスとモジュールは名前的(nominal)のままです。
  • RBSインターフェースとRigorのオブジェクトシェイプは構造的なダックタイピング(duck typing)を提供します(structural-interfaces-and-object-shapes.mdを参照)。
  • Rubyの真偽性(truthiness)はfalsenilのみが偽 — それだけです。
  • Rubyの等価性、case等価性、respond_to?method_missing、特異メソッド、モジュール包含は実行時の挙動であり、他言語からコピーするのではなく、Rubyのセマンティクス、RBS署名、プラグイン事実を通じてモデル化しなければなりません。
  • アプリケーションのRubyコードにRigor専用の注釈構文は持ち込みません。既存のRBS、rbs-inline、Steep互換の注釈は型のソースとして受け付けられ、Rigor固有の構文として扱われることはありません。

本仕様は、最初の実装マイルストーンではなく、理想的な型モデルを基準に組み立てられています。優先度は次の順です:

  1. すべてのRBS型とRBSのすべてのエクスポート規則を保つ。
  2. ナローイング(narrowing)とメンバー利用可能性についてはRuby実行時の挙動を真実の源とする。
  3. 精度の段階的な喪失をuntypedのprovenanceで明示的に表す。
  4. 制御フローの事実を、ブロックレベルの分岐ラベルだけでなく、式エッジでのスコープ遷移として扱う。
  5. 構造的インターフェースとオブジェクトシェイプを通じてRubyのダックタイピングをサポートする。ただし、すべてのクラス互換性を構造的にすることはしない。
  6. プラグインやRBS::Extendedが事実、効果、動的リフレクションを持ち込めるようにする一方で、スコープ適用と正規化の所有権は解析器に保つ。
  7. Rigorが著作するすべての型にロバストネス原則(Postelの法則)を適用する — 戻り値は厳密、引数は寛容。これにより精度が下流に伝播し、呼び出し側の強制変換ノイズを避けられる。
  8. 動作しているコードに対する偽陽性を最小化する。実行されるプログラムはそれ自身の正確性の第一の証拠である;診断は、ランタイムが到達しない最悪ケースについて著者に警報を鳴らしてはならず、ロジックが本当に必要とする以上の防御的コードを誘発してはならない。偽陽性の規律を参照。

設計優先度8は第一級の価値だ — RBSの保存やロバストネス原則と同じ土俵にあり、チューニングノブではない。

  • 動作しているプログラムが最も重要な事実だ。静的解析が最悪ケースの健全(soundness)な読み取り — T | nil、欠落しているかもしれないメソッド — を導出しても、それが実行され、テストでカバーされたプログラムが実際には到達しないものであるとき、ランタイムの証拠が静的な最悪ケースを上回る。Rigorはそのようなサイトを慎重に報告し、リリース品質のコードベースはそこからの診断をほとんどまたはまったく表面化しないことが期待される。

  • 合理的な防御的プログラミングは歓迎され、Rigorはそれについて沈黙を保つ。本物の外部入力境界をガードすること、正直にnil可能な値を扱うこと、信頼境界でバリデートすること — これらは良いRubyだ。Rigorはそれらを冗長としてフラグしたり、それらに異議を唱えたりしてはならない。

  • Rigorが誘発してはならないのは過剰な防御性だ。型情報がすでに不要だと証明しているガード — ナローイングが非nilと確立した値に対するnilチェック、クラスがすでに既知の値に対するis_a? — や、ロジックが必要とする以上のbelt-and-suspendersコーディングに著者を押しやる診断は、設計の失敗だ。著者は、プログラム自身のロジックが正当化する以上に保守的または冗長にされてはならない。境界線は必要性だ: ロジックが本当に必要とするガードは歓迎される;型が無意味にするガードはノイズだ。

  • エンジンとルール作業への帰結。動作しているコードに対する診断を増やす精度変更や新しいルールは、それがより多くを捕捉するときでも疑わしい — 偽陽性のコストは重く秤にかけられ、決して無料として扱われない。投機的な診断よりも、辞退すること(Dynamicにナローイングする、何も発行しない)が好まれる。これは、ロバストネス原則が型著作の側で運ぶ(節2の回避策増殖アンチパターン)のと、ベースライン(baseline)メカニズム(ADR-22)が採用の側で運ぶのと、同じ意図の診断発行における表現だ。

本仕様は長期的な型モデルを記述します。最初のユーザー向けリリース(v1)は意図的に範囲を絞ったスライス(slice)を出荷します。境界は次のとおりです:

  • 完全な仕様 — 事実安定性のバケット、ケイパビリティ(capability)ロールのカタログ、ミューテーションの集約集合、Dynamic[T]代数、型演算子、RBS::Extendedのスキーマ — は規範性を持ちます。内部データ構造はv1にも存在してかまいませんが、ユーザーに見えるナローイング表面ではまだそれを利用しないことがあります。
  • v1のナローイング表面は、最初のリリースでエンドユーザーに対して有効化される導出規則のサブセットです。
  • 後続のリリースは、データ構造がすでにサポートする規則を使ってナローイング表面を拡張します。0.1.xプレビューラインを通じて、その多くはすでに出荷済みです(プロシージャ内のファクト伝播、プラグイン供給のフロー貢献、def.override-*ファミリー)。各追加は、以前に出荷された挙動を保つよう段階的にランディングします。

出荷済みと保留の境界の詳細は、関連するトピック節(control-flow-analysis.mdstructural-interfaces-and-object-shapes.mdrbs-extended.mdなど)に現れます。

互換性の階層は次のとおりです:

  • RBSとrbs-inlineは、型構文およびインライン注釈の互換性に関する第一の規範。
  • Steep 2.0の挙動は、文章による仕様が挙動を未定義にしている部分について、既存の注釈をどう解釈するかに関する第二の規範。
  • TypeScript、PHPStan、Python typingはデザイン参照であり、構文互換のターゲットではない。

3者が異なるとき、RigorはREADME.mdに記載された解決順序に従います。

インライン注釈の取り扱い: RigorはRBSとrbs-inlineの構文に対して100% 互換でなければならず、インライン注釈の解釈と優先順位についてはSteep 2.0の挙動に従うべきです。既存のrbs-inlineおよびSteep互換の注釈は型のソースとして公式に扱います。Rigorはそれらを書き換えてはならず、複雑であることだけを理由に警告してはならず、解析を始めるために# rbs_inline: enabledを要求してはなりません。# rbs_inline: enabled# rbs_inline: disabledのようなrbs-inline設定ディレクティブのみが解釈されます。rbs-inlineの注釈コメント自体(#: String# @rbs、パラメータ注釈など)は、存在すれば常にパースされ利用されます。

完全な型定義の置き場としては、独立した.rbsファイルや生成されたスタブが引き続き推奨されます。それでもインライン注釈は存在すれば実在の契約(contract)であり、単なるヒントではありません。実装側のチェックは契約の出所に依存しません。#: voidで書かれた戻り値型、# @rbsで書かれたメソッド型、rbs-inlineスタイルで書かれたパラメータ型、生成されたスタブ、外部.rbs宣言は、いずれも同じように実装を制約します。

インライン注釈のスタイルガイド

Section titled “インライン注釈のスタイルガイド”

スタイルガイドは「型を.rbソースに書くべきか」という問いだけを扱います。妥当性(validity)には影響しません:

  • #: void#: botは、意図を表現し有用な推論境界を作るときに強く推奨されます。
  • #: bool#: String#: Userのような短い戻り値は中立で、意図を明確にしたいなら著者が書いてもかまいません。
  • 複雑なインライン型 — ユニオン、ジェネリクス、レコード、ネストされたメソッド型 — は妥当なRBS/rbs-inline入力であり、受け付けなければなりません。Rigorのスタイルガイドは.rbsや生成スタブへの移動を好みますが、Rigorは単にこれを使ったというだけで診断を出してはなりません。

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.