pockestrap

Programmer's memo

ruby/rbsに取り込まれた私のパッチ

この記事はRuby 3.0 Advent Calendar 17日目の記事です。

qiita.com

昨日の記事は id:gamelinks007 さんで「C APIのヘッダーが分割された話」でした。

gamelinks007.hatenablog.com


この記事では、Ruby 3に同梱されるrbsに対して私が書いたPull Requestを紹介します。本日(2020-12-17)時点で64個のPull Requestがマージされているようです。

古い順に紹介していきます。

ref: https://github.com/ruby/rbs/pulls?page=1&q=is%3Apr+author%3Apocke+is%3Amerged


github.com

gemspecのfilesで絶対パスを使っていてコケていたのを修正。

この頃はまだruby-signatureと呼ばれていたんですね、懐かしい。


github.com

Kernel.#pの型を修正。pは引数の型を返すけど、nilを返すと誤った型付けがされていた。


github.com

Kernelモジュールの型定義を修正。 これ頑張った気がする。

このへんはRHC起因でやるぞとなったやつな気がする。 https://rhc.connpass.com/event/151557/


github.com

テストコードのボイラープレートを生成するコードを書いた。


github.com

自動生成されたファイルをRuboCopの検査から外した。 これは手元のraccが古かったのが原因だった気がする


github.com

RBSで空Tupleが許可されているけどドキュメント上はそうなっていなかったのを直した。


github.com

WriterというRBSを書き出すためのクラスがあるのだけど、それが空タプルやoptionalなsymbolで壊れていたので直した。 しかし:foo ?ってダサいよな。(:foo)?とか書けないかな。

このころはrbsfmtを作っていたけど、だるくて放置している。コメントをいい感じにするのがだるそう…


github.com

RBSを読み込んでそれをまたWriterで書き戻すようなときに、行間が空いていたらそれを維持するようにした。

ruby/rbsにある.rbsを全部読み込んでWriterを通した結果意味が変わらないかをテストするコードもついでに足した。


github.com

hashメソッドの定義が間違っていて壊れていたので直した。 あとPRの最初の状態だとhashメソッドの使い方が間違っていてそれを教えてもらった。


github.com

bin/setupを使うようにドキュメントを書いた。自分はbin/setupの存在を忘れがちであんまり使わないのだけど…


github.com

rbsコマンドのヘルプメッセージの出力をいい感じにした。


github.com

rbs prototype rbが引数のないFCALLや引数のないyieldでコケていたので直した。


github.com

仮引数名にキーワードを使えるようにした。


github.com

::Fooのように絶対パスでクラスが参照されているとFooが定義されていなくてもそれっぽい値が返ってきてしまう問題を直した。これ難しかった気がする。


github.com

RBSclass << selfを解釈するようにした。

selfじゃないときもとりあえずselfと同じように扱っているのだけど、それが原因でぶっ壊れているところがあって、そこは直したい気持ち…。


github.com

よく覚えていないけど、include元のモジュールで定義されている定数をinclude先のモジュールのnamespaceで参照しようとしたときにエラーになっていたのを直したっぽい。


github.com

Steepを使っていて、RBSの定義がなにかおかしいときに変なエラーになってしまっていたのを直した。


github.com

rbs prototype rbでkwrestが不必要に出力されてしまっていたのを直した。


github.com

テストメソッド名の重複を直した


github.com

Rubyのmasterでkeyword argsがRuby 3の仕様になったのに合わせてテストが落ちていたので、ruby2_keywordsメソッドを使ってなんとかした。 original ideaはmameさんらしい。


github.com

テストメソッド名の重複を直した。


github.com

markdownでリストをネストするのに必要な空白の数が足りていなかったので足した。o

GitHub Flavored Markdown needs four spaces to indent unordered list items in ordered list items.

って言ってるけど"four spaces"は厳密には嘘で4つじゃ足りないこともあるのだよな。という記事を書こう書こうと思いつつ書けていない…


github.com

Hashの型を書いた。大変だったやつ


github.com

たぶんHashの型を書いているときに気がついたやつで、ドキュメントが間違っていたのを直した。


github.com

ライセンスの書き方が微妙な感じだったのをいい感じにした。


github.com

CLI--no-stdlibオプションが壊れていたのを直した。


https://github.com/ruby/rbs/pull/207github.com

RBSのsyntax checkだけを行うコマンドを追加した。これをエディタから使うとRBSを書きつつSyntax Checkが簡単にできて便利。


https://github.com/ruby/rbs/pull/208github.com

rbs prototype rbprivate def fooスタイルのメソッド定義が抜け落ちていたのを直した。このスタイルのメソッド定義好き。


https://github.com/ruby/rbs/pull/209github.com

rbs prototype rbで戻り値の型をいい感じに推測するようにした。prototype rbがでかくなっていく最初のパッチという感じがする…。


https://github.com/ruby/rbs/pull/212github.com

Pathnameの型を足した。これはRBS Railsで使っていてほしかったからだっけかな。


https://github.com/ruby/rbs/pull/213github.com

String#encodeのfallbackオプションの型が違っていたのを直した。

bugs.ruby-lang.org

そしてそもそもRuby側の実装も壊れていたっぽいので報告した。


https://github.com/ruby/rbs/pull/219github.com

Dir.openの型が間違っていたので直した。


https://github.com/ruby/rbs/pull/290github.com

Enumerator::Yielderの型を直した。同じ頃るりまのドキュメントも書いていた気がする。


https://github.com/ruby/rbs/pull/291github.com

Ruby 2.7で追加されたEncoding::CESU_8の型定義を追加した。これもるりまのドキュメントを書いていて気がついたやつな気がする。


https://github.com/ruby/rbs/pull/292github.com

builtinのFiberの型を直した。

これもるりまのドキュメントを書いていたり、あとはRDocの記述も間違っていたのでbugsにレポートしたりしていた。

https://github.com/rurema/doctree/pull/2277github.com

bugs.ruby-lang.org


https://github.com/ruby/rbs/pull/293github.com

ドキュメントの修正をした


https://github.com/ruby/rbs/pull/296github.com

require 'fiber'すると生えてくるFiberのメソッドの型を足した。


https://github.com/ruby/rbs/pull/303github.com

rbs prototype rbで、メソッド本文が複数文あっても戻り値の型を推測するようにした。


https://github.com/ruby/rbs/pull/304github.com

_始まりのメソッドが?!で終わっているとSyntax Errorになってしまっていたので直した。


https://github.com/ruby/rbs/pull/306github.com

mutex_mの型を書いた。Railsが依存していてRBS Railsでほしかった。


https://github.com/ruby/rbs/pull/314github.com

テストのボイラープレートを生成するgenerate:stdlib_test rake taskが動いていなかったのを直した。これ今はちゃんと動いているのかな……


https://github.com/ruby/rbs/pull/316github.com

loggerライブラリの型を足した。 これもRailsで使っていて必要になったやつ。

Loggerはそこそこのサイズがあって多少の気合を出して書いた。


https://github.com/ruby/rbs/pull/317github.com

IO周りの型を直した。IO#writeはrest argumentsを受け取るらしい。このPRを見返すまでそんなことすっかり忘れていた。このPRを書いた時の自分はなんでこれに気がついたのだろう


https://github.com/ruby/rbs/pull/319github.com

ゴミを消した。

このPRの後でゴミの検出が自動化されていた。便利。 https://github.com/ruby/rbs/blob/49e4d7219d52e0e1ca25c91b2c1b33e7e8a98dd1/goodcheck.yml#L2-L12


https://github.com/ruby/rbs/pull/327github.com

この頃RBSのパースが遅いという話題があって、それをサッと速くした。

いつもどおりstackprofでプロファイルを取っているとStringScanner#charposがめっちゃ遅くて、実装を見てみるとたしかにめっちゃ遅そうな実装だった。 https://github.com/ruby/strscan/blob/d0c82c20c64323c45ee275f09e5a951a291f1ee2/ext/strscan/strscan.c#L442-L453 これはscannerが読み込んだ位置を文字単位で返すAPIなのだけど、scannerは読み込んだ位置をバイト単位でしか保持していない。 なので読み込んだ位置のバイトを使ってString#bytesliceを呼んで、その結果の部分文字列に対してString#lengthを呼んでいる。遅そう。

というわけでStringScanner#charposが遅いので、これの呼び出し回数を減らした。 またRBSがASCIIだけで書かれている場合にはバイト単位の位置で充分なためcharposの代わりにposを使うようにした。 つまり、RBSはASCIIだけで書くと速い。


https://github.com/ruby/rbs/pull/331github.com

RBS::Environmentをうっかりpすると画面が破滅するのを直した。


https://github.com/ruby/rbs/pull/334github.com

rbs prototype rbで重複するメソッドは1つにまとめるようにした。

class C
  if RUBY_VERSION >= '2.7'
    def foo
      do_something_27
    end
  else
    def foo
      do_something
    end
  end
end

PRのdescriptionにもあるとおり、こういうコードがあるとfooに対する定義が2回出力されてエラーになってしまうため。こういうコードはRailsの内部とかで実際にある。


https://github.com/ruby/rbs/pull/337github.com

重複する定数がある際にいい感じのエラーが出ずにNoMethodErrorになってしまっていたのを直した。 これは実際に重複する定数を生成してしまって意味不明なエラーが出ていたとかだったと思う


https://github.com/ruby/rbs/pull/338github.com

rbs validateを速くした。当時のRBS RailsRBSに対して3.77倍速くなったので結構でかい。

コードを読んでなんとなくの理解しかできていないのだけど、rbsでは型引数をメソッドに適用するために全てのメソッドに対してsubメソッドでメソッド型を表すオブジェクトを作り直していた。 一方型引数を使っているメソッドというのは多くなくて、かつこのオブジェクトの作り直しは型引数を使っていないコードに対しては無意味なので、そこで無意味に遅くなってしまっていた。

なのでこのPRでは型引数を使っていないメソッド定義ではオブジェクトを生成しないようにして速くした。みたいな感じだったと思う。


https://github.com/ruby/rbs/pull/457github.com

rbs prototype rbでaliasをサポートした。

これでRailsのコードに対してRBSを生成し直したらalias周りで色々バグが見つかって、いくつかIssueに報告した。むずそう。 https://github.com/ruby/rbs/pull/516


https://github.com/ruby/rbs/pull/462github.com

Enumerable#to_hはブロック引数を受け付けるのだけど、そうなっていなかったので直した。

これはRBS Railsを触っているときにto_hの定義を見に行きたくなって見に行ったら「あれ?ブロック受け取らなかったっけ?」となって足したような気がする。


https://github.com/ruby/rbs/pull/463github.com

RBSが意図しないEOFでSyntax ErrorになったときにNoMethodErrorになってしまっていたのを直した。

raccのためのnext_tokenメソッドが返す値が間違っていたのが原因だった。raccの使い方に少し詳しくなった。


https://github.com/ruby/rbs/pull/465github.com

rbs prototype runtimeがhash spread構文でエラーになってしまっていたのを直した。


https://github.com/ruby/rbs/pull/481github.com

rbs prototype rbpublicprivatemodule_functionに対応した。

正直publicprivateはおまけで、module_functionの対応が欲しかった。 そしてRBSにはprotectedがない。


https://github.com/ruby/rbs/pull/482github.com

Singleton moduleの型を書いた。

この型があって便利かと言うと、まあinclude Singletoninstanceメソッドがあっても型エラーにならなくなるぐらいかなあ。

class SingletonSingletonTest、ひどい名前だ


https://github.com/ruby/rbs/pull/483github.com

RBSにmonitor libraryの型を追加しようとMonitorMixinに対してrbs prototype runtimeしたらエラーになって、それの対応。 rbs prototype runtimeをarguments forwarding syntaxで定義されたメソッドに対して使うと、Syntax Errorなコードを生成していた。


https://github.com/ruby/rbs/pull/485github.com

monitor libraryの型を書いた。これもRailsが依存していたから追加しておきたかった型。


https://github.com/ruby/rbs/pull/486github.com

rbs prototype rbmodule_function対応のバグ修正。別の場所で定義されたメソッドをmodule_functionしようとしているとエラーになっていた。これはRailsの型を生成しようとして気がついたやつな気がする。


https://github.com/ruby/rbs/pull/487github.com

rbs prototype rbでrefinementsを無視するようにした。

RBSはrefinementsをサポートしていないし、まあ無視していいかなと言う気持ち。


https://github.com/ruby/rbs/pull/491github.com

rbs prototype rbpublicprivateのサポートにもバグがあってそれを直した。なんかこの辺のコード死ぬほど難しくてむずい。書いたの自分だけど……


https://github.com/ruby/rbs/pull/492github.com

rbs prototype rbextend selfをサポートした。 私はextend selfを好きでよく書くからこれが出てくれるのは嬉しい。


https://github.com/ruby/rbs/pull/505github.com

soutaroさんが実装したsingletonのattr_*rbs prototype rbでもサポートした。


https://github.com/ruby/rbs/pull/517github.com

この記事を書くために自分のPRを見返していたら、loggerの型のTODOの消化忘れを見つけたので直した。 loggerの型を書いたときにはMonitorMixinの型はまだなかったからincludeできなかったのだけど、MonitorMixinの型を書いたのでincludeできるようになった。


https://github.com/ruby/rbs/pull/518github.com

これもこの記事を書いていて気がついた問題で、前に追加したwriterのsmoke testでテスト対象のRBSファイルを増やした。