Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The newsletter of RBS updates

pocke
September 10, 2021

The newsletter of RBS updates

pocke

September 10, 2021
Tweet

More Decks by pocke

Other Decks in Programming

Transcript

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

    View Slide

  2. 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!

    View Slide

  3. 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

    View Slide

  4. 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

    View Slide

  5. 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!

    View Slide

  6. 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

    View Slide

  7. Introduce RBS and related
    softwares

    View Slide

  8. 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+

    View Slide

  9. 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

    View Slide

  10. 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

    View Slide

  11. 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)

    View Slide

  12. New feature: rbs collection

    View Slide

  13. 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💎

    View Slide

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

    View Slide

  15. 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

    View Slide

  16. 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

    View Slide

  17. 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

    View Slide

  18. 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

    View Slide

  19. 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

    View Slide

  20. rbs collection solves the
    problems!

    View Slide

  21. 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

    View Slide

  22. 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

    View Slide

  23. 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)

    View Slide

  24. 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

    View Slide

  25. 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)

    View Slide

  26. Mechanism of rbs collection

    View Slide

  27. 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.

    View Slide

  28. 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

    View Slide

  29. New feature: Bounded Type
    Parameters

    View Slide

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

    View Slide

  31. 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

    View Slide

  32. 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)

    View Slide

  33. 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

    View Slide

  34. 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

    View Slide

  35. New feature: Generic Type Aliases

    View Slide

  36. Generic Type Aliases
    RBS v2 will introduce generic type aliases.

    View Slide

  37. 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.

    View Slide

  38. 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!

    View Slide

  39. Other updates

    View Slide

  40. 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

    View Slide

  41. Conclusion

    View Slide

  42. 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!

    View Slide