こんにちは、フルタイムRubyコミッタとして働いてる遠藤(@mametter)です。
Ruby 3 は「静的型解析」を備えることが目標の 1 つになっています。遠藤が開発してる TypeProf は Ruby 3 の静的型解析エコシステムの中の 1 ツールです。しかし Ruby 3 の静的解析というと、RBS、TypeProf、Steep、Sorbet などいろいろなツール名が出てきてよくわからない、という声を何回か聞いたので、かんたんにまとめておきます。
3 行まとめ
- RBS:Ruby の型情報を扱う言語。Ruby 3 にバンドルされる。
- TypeProf:型注釈のない Ruby コードを型解析するツール。Ruby 3 にバンドルされる。
- Steep/Sorbet:Ruby で静的型付けのプログラミングができるツール。
詳しくはそれぞれ以下で解説します。
RBS とは
RBS は、Ruby 3 の型を扱うための基盤です。おおよそ、次の 4 種類のものからなります。
- RBS 言語:Ruby プログラムの型情報を記述するための記法(拡張子 .rbs)
- Ruby 組み込みライブラリの型情報:Ruby の組み込みクラス(
Array
やString
など)の型情報を書いた.rbsファイル群 - RBS ライブラリ:.rbs ファイルのパースや解析などをするライブラリ
- rbs コマンド:.rbs ファイルを扱うための便利コマンド
いろいろありますが、Ruby プログラマが直接意識するのは 1 つめの RBS 言語だけだと思います *1。よって、単に RBS と言ったら「RBS 言語」、または「RBS 言語で書かれたソースコード」を指すと考えるのがよいと思います。
RBS 言語の例を示しておきます(core/string.rbsよりものすごく抜粋)。Ruby っぽいですが、Ruby ではない別の言語になっています。
classStringdef empty?: () -> bool end
この記述は、Ruby の組み込みクラスである String
クラスの型情報(RBS言語で書かれている)の抜粋で、empty?
という無引数のメソッドを持っていて、bool
を返すということを表しています。
RBS ライブラリを使うと、こういう .rbs ファイルをパースして抽象構文木を得ることができます。
rbs コマンドは、.rbs ファイルを読んでメソッドを検索するなどができます。
RBS はそれ単体で何かをするものではなく *2、Ruby 3 の型情報を扱うツールが共通で使いたくなるものを集めた gem になっています。この gem は Ruby 3 に同梱されます。しかし基本的には型解析ツール向けの gem であり、普通の Ruby プログラマは RBS 言語を読み書きすることはあっても、RBS gem を直接使うことはあまりないと思います。
TypeProf とは
TypeProf は、型注釈のない Ruby コードを無理やり解析する静的型解析器です。Ruby 3 にバンドルされます。TypeProf は RBS 基盤を活用して作られています。
TypeProf の特徴はなんといっても、「型注釈を書かなくてもなんとなく型解析っぽいことができる」という性質に極振りして設計されているところです。
キーポイントは、メソッド呼び出しの情報を活用して解析するところです。
これにより、たとえばdef hello(user) ... end
という型注釈が一切ないメソッドに対しても、hello(User.new)
という呼び出しがあれば「メソッドhello
はUser
インスタンスを引数に取る」ということを推論します。
また、一部のクラスに RBS 言語で型情報を書いて TypeProf に与えることもできます。TypeProf はユーザが明示した型情報を無条件に信用するので、解析精度や解析速度が向上します。
TypeProf について詳しくは別の記事で解説しています。
Steep/Sorbet とは
Steep は、Ruby の静的型検査器です。RBS を使って、伝統的な漸進的型付けによる型検査を行うことができます。 単に型エラーを検出できるだけではなく、LSP を実装しているので、エディタ上での型エラー表示、補完、ドキュメント表示なども実装されています。 現状で RBS を使って便利さを実感できるのは、Steep だけです。 このへんがわかりやすい記事にリンクしておきます。
Sorbet は、また別の Ruby の静的型検査器です。 こちらは RBS ではなく RBI という独自形式の型注釈を使います(RBS から RBI への変換器も開発されています)。 ものすごくざっくり言ってしまうと、できることは Steep とおおよそ同じです。 とはいえ、Stripe や Shopify という大企業ですでに数年ほど経験を積んでいるので、完成度はとても高いです。 解析器はC++で書かれていて、解析速度をものすごく重視しています。
Steep も Sorbet も Ruby 3 にバンドルされる予定はありません。 Ruby の設計者である matz が、「型注釈を書くことを Ruby本体として推進しない」と判断した結果です *3。この判断と相性の良い TypeProf は将来の期待とともに Ruby 3 にバンドルされますが、型注釈を書くことをいとわない人は Steep や Sorbet を使うとよいと思います。
なお、Steep 自体はバンドルこそされませんが、RBS はもともと Steep の型注釈言語でした。 Ruby 組み込みライブラリや gem の型情報を各種ツール間で共通化したかったので、RBS という形で共通基盤として切り離され、Ruby本体に同梱されることになりました。
再度まとめ
- RBS: Ruby 3 の型情報を扱う言語を始めとする基盤。Ruby 3 にバンドルされる。
- TypeProf: 型注釈のない Ruby コードを型解析するツール。Ruby 3 にバンドルされる。現状の主機能は Ruby コードからの RBS スタブ生成。
- Steep/Sorbet: Ruby の静的型検査器。型注釈を書く必要はあるが、Ruby で静的型の便利なプログラミング体験ができる。IDE での補完やドキュメント表示も。