Slide 1

Slide 1 text

The newsletter of RBS updates RubyKaigi Takeout 2021🍔💨 Sep. 10th

Slide 2

Slide 2 text

pp self ● Masataka Pocke Kuwabara ● Software Engineer at Bit Journey, Inc. ○ Developing Kibela, an information sharing tool. https://kibe.la ● A maintainer of RBS ● A CRuby committer since Mar. 2021 ← NEW!

Slide 3

Slide 3 text

First, Thanks for all RBS contributors!👏👏 AaronC81, Adrian-Hirt, Afront, CariWest, HoneyryderChuck, MITSUBOSHI, Morriar, PanosCodes, YutaGoto, Yuuki77, a2ikm, ahazem, aikyo02, alts, andrewmcodes, berkos, cky, connorshea, donaldong, duderman, floor114, guillaumebriday, hanachin, hargoniX, hjwylde, hsbt, jeremyevans, jocmp, johansenja, k0kubun, kachick, kddnewton, kmizu, ko1, ksss, kunitoo, kyanny, linhpham, mame, marcandre, masahito1997, meganemura, mihyaeru21, mtsmfm, natsuokawai, nobu, ochaochaocha3, ohbarye, palkan, pocke, pointlessone, raosush, s4na, satoryu, sbeckeriv, soutaro, south37, szTheory, tadd, taki, waka, wat-aro, ybiquitous, ykpythemind, ysakasin note: ascii order, (..Time.parse('2020-08-20').cover?(contributed_at) full list: https://github.com/ruby/rbs/graphs/contributors and https://github.com/ruby/gem_rbs_collection/graphs/contributors

Slide 4

Slide 4 text

Goal ● You get hints to introduce RBS to your application ● Announce RBS updates for Ruby 3.1 ○ RBS v2 will be released for Ruby 3.1

Slide 5

Slide 5 text

Support page This talk is pre-recording, so it may have updates between recording and event date. I wrote the additional information into the following GitHub repository. https://github.com/pocke/rubykaigi-2021 And I’m watching this talk so feel free to ask me!

Slide 6

Slide 6 text

Agenda: RBS Updates ● Introduce RBS and related softwares ● New feature: rbs collection ○ The main topic! ● Language Updates (Thanks soutaro-san!) ○ Bounded type parameter ○ Generic type aliases ● Other updates ○ Signature updates ○ Performance Improvements

Slide 7

Slide 7 text

Introduce RBS and related softwares

Slide 8

Slide 8 text

What’s is RBS? ● RBS is a language to describe Ruby types. ● It is a bundled gem since Ruby 3.0. ● You can also gem install rbs in Ruby 2.6+

Slide 9

Slide 9 text

Repositories RBS is developed under two GitHub repositories ● https://github.com/ruby/rbs ○ the rbs gem ○ rbs command, rbs library, and RBS files for Ruby builtin and stdlibs. ● https://github.com/ruby/gem_rbs_collection ○ RBS for 3rd party gems, such as rails, nokogiri, etc ○ Similar to DefinitelyTyped in TypeScript

Slide 10

Slide 10 text

Let’s contriubte to ruby/gem_rbs_collection ● It’s one of the easiest parts to contribute RBS ● We recommend writing gem RBS partially ○ RBS for gem’s all features is not required, focus the main features

Slide 11

Slide 11 text

Related softwares ● TypeProf: https://github.com/ruby/typeprof ○ A type analysis tool for Ruby code based on abstract interpretation ● Steep: https://github.com/soutaro/steep ○ Static Type Checker, using RBS ● RBS Rails: https://github.com/pocke/rbs_rails ○ RBS generator for Ruby on Rails ● Sorbet: https://github.com/sorbet/sorbet ○ Static Type Checker, using RBI (another language describes Ruby Type)

Slide 12

Slide 12 text

New feature: rbs collection

Slide 13

Slide 13 text

New feature: rbs colllection ● It manages dependent libraries’ RBSs ○ In short, Bundler for RBS ● I’m developing this feature ● rbs collection command has been released! ○ As experimental for now, it will be GA on RBS v2 ○ You can use it with gem install rbs now💎

Slide 14

Slide 14 text

Motivation Before rbs collection, managing libraries’ RBSs is not smart. Let’s look an example to prepare libraries’ RBSs for a Rails app

Slide 15

Slide 15 text

Motivating Example: Enable RBSs for a Rails app First, download gem_rbs_collection as git submodule $ git submodule add https://github.com/ruby/gem_rbs_collection.g it gem_rbs_collection

Slide 16

Slide 16 text

Motivating Example: Enable RBSs for a Rails app Then, rbs command is available with the following super many options! $ rbs -rlogger -rpathname -rmutex_m -rdate -rmonitor -rsingleton -rtsort -rtime --repo=gem_rbs_collection -rrack -ractivesupport -ractionpack -ractivejob -ractivemodel -ractionview -ractiverecord -rrailties validate

Slide 17

Slide 17 text

Motivating Example: Enable RBSs for a Rails app TypeProf needs the same options $ typeprof -rlogger -rpathname -rmutex_m -rdate -rmonitor -rsingleton -rtsort -rtime --repo=gem_rbs_collection -rrack -ractivesupport -ractionpack -ractivejob -ractivemodel -ractionview -ractiverecord -rrailties target.rb

Slide 18

Slide 18 text

Example: Enable RBSs for a Rails app (step 4) And, Steep needs another configuration file, Steepfile. target :app do signature 'sig' check 'app' repo_path "gem_rbs_collection" library 'pathname', 'logger', 'mutex_m', 'date', 'monitor', 'singleton', 'tsort', 'time', 'rack', 'activesupport', 'actionpack', 'activejob', 'activemodel', 'actionview', 'activerecord', 'railties' end

Slide 19

Slide 19 text

Conclusion of the motivations ● We need resolve dependencies by hand ○ The above examples, the human resolves “my app depends on Active Support, then Active Support depends on logger and …” ● To download, We need git submodule or copying RBSs ○ It’s too primitive. How controlling versions of 3rd party RBSs? ● To load, We need different ways between RBS, Steep, and TypeProf

Slide 20

Slide 20 text

rbs collection solves the problems!

Slide 21

Slide 21 text

What’s rbs collection? ● rbs collection is a command to manage libraries’ RBSs ● It does the following things ○ Resolve dependencies automatically ○ Download necessary RBSs ○ Load RBSs from one configuration file

Slide 22

Slide 22 text

Usage example: rbs collection for a Rails app First, you need to generate the configuration file, rbs_collection.yaml # to install the latest version of RBS $ gem install rbs $ rbs collection init created: rbs_collection.yaml

Slide 23

Slide 23 text

Usage example: rbs collection for a Rails app Then, edit the generated config file, add the following line + gems: [name: pathname, name: logger, name: mutex_m, name: date, name: monitor, name: singleton, name: tsort, name: time, name: set] (I’ll describe meaning of this diff)

Slide 24

Slide 24 text

Usage example: rbs collection for a Rails app Then install RBSs. Note that rbs collection needs Gemfile.lock to resolve the dependencies $ vim Gemfile && bundle install $ rbs collection install

Slide 25

Slide 25 text

Usage example: rbs collection for a Rails app Finally you can use RBS related tools without CLI options! $ rbs validate $ typeprof target.rb $ steep init && steep check Everything is going well! (NOTE: Steep and TypeProf haven’t been implemented yet maybe)

Slide 26

Slide 26 text

Mechanism of rbs collection

Slide 27

Slide 27 text

Mechanism of rbs collection ● It resolves dependencies with Gemfile.lock, and writes them to the lockfile, rbs_collection.lock.yaml ● It copies libraries’ RBSs with the lockfile from the sources, ruby/gem_rbs_collection GitHub repo in most cases. ● It loads RBSs with the lockfile for rbs, typeprof, steep commands.

Slide 28

Slide 28 text

Known Issue ● rbs collection doesn’t resolve dependencies of standard libraries ○ For example, logger, optparse, etc… ○ Because standard libraries don’t need to be added to gemspec/Gemfile in order to require. ● I’ll fix this problem soon by introducing a configuration file, such as manifest.yaml to each gem

Slide 29

Slide 29 text

New feature: Bounded Type Parameters

Slide 30

Slide 30 text

Bounded Type Parameters RBS v2 will introduce Bounded Type Parameters. It allows you to specify an upper bound to Type Parameters.

Slide 31

Slide 31 text

Motivating Example: PrettyPrint class ● The first parameter of PrettyPrint.new is the destination of printing. ○ e.g. PrettyPrint.new(str) ○ The output is given with << method

Slide 32

Slide 32 text

Motivating Example: PrettyPrint classs PrettyPrint.new("") # OK (String#<<) PrettyPrint.new(STDOUT) # OK (IO#<<) PrettyPrint.new([]) # OK (Array#<<) PrettyPrint.new(true) # Error (No TrueClass#<<) PrettyPrint.new(3) # Error (Integer#<< doesn't accept String)

Slide 33

Slide 33 text

Without bounded type parameters # RBS class PrettyPrint attr_reader output: _PPOut def initialize: (?_PPOut output) -> void end interface _PPOut def <<: (String) -> void end # Ruby PrettyPrint.new("") .output.size # _PPOut doesn't have #size PrettyPrint.new([]) .output.join("") # _PPOut doesn't have #join

Slide 34

Slide 34 text

Bounded type parameters solve this problem # RBS class PrettyPrint[X < _PPOut] attr_reader output: X def initialize: (?X output) -> void end interface _PPOut def <<: (String) -> void end # Ruby PrettyPrint.new("") .output.size # X == String, String#size exists PrettyPrint.new([]) .output.join("") # X == Array, Array#join exists

Slide 35

Slide 35 text

New feature: Generic Type Aliases

Slide 36

Slide 36 text

Generic Type Aliases RBS v2 will introduce generic type aliases.

Slide 37

Slide 37 text

Motivating Example: defining tree types type int_tree = { value: Integer, left: int_tree?, right: int_tree? } type string_tree = { value: String, left: string_tree?, right: string_tree? } We need to define the most same types for each type.

Slide 38

Slide 38 text

Generic Type Aliases solve this problem type tree[T] = { value: T, left: tree[T]?, right: tree[T]? } type int_tree = tree[Integer] type string_tree = tree[String] type cat_tree = tree[Cat] We can define generic tree[T] type to make them DRY!

Slide 39

Slide 39 text

Other updates

Slide 40

Slide 40 text

Other updates ● Signature updates ○ 80 RBS files added/updated since RBS v1 for Ruby 3.0 ● Performance Improvements ○ rbs validate command has been 3x faster than RBS v1 ○ Parsing RBS will be 5x faster by an RBS parser written in C by soutaro-san ● Many bug fixes See the CHANGELOG for full changes! https://github.com/ruby/rbs/blob/master/CHANGELOG.md

Slide 41

Slide 41 text

Conclusion

Slide 42

Slide 42 text

Conclusion ● RBS v2 will introduces many new features, such as rbs collection and language updates ● It also includes signature updates, performance improvements ● We’re developing RBS for Ruby v3.1! Thanks for listening!