Skip to content

Release Note 3.0

Soutaro Matsumoto edited this page Feb 22, 2023 · 16 revisions

Some of the highlights in RBS 3.0 are:

  • Add class/module alias syntax (#1219)
  • Add use syntax (#1224)
  • RBS collection skips loading application gems (#1222)
  • RBS collection supports local source (#854)
  • The bundled core/stdlib RBS signatures are updated to Ruby 3.2 (#1237, #1238, #1240, #1241, #1242)

You can install it with $ gem install rbs or using Bundler.

gem 'rbs', '~> 3.0.0'

See the CHANGELOG for the details.

There are breaking changes in APIs from RBS 2.8. Read the upgrade guide below if you develop with RBS library.

Add class/module alias syntax

The spec: https://hackmd.io/@soutaro/HkgF2HHco

The class/module alias syntax allows defining alias of classes and modules.

class HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess

The sample code above defines ::HashWithIndifferentAccess that is another name of ::ActiveSupport::HashWithIndifferentAccess.

The difference between type alias syntax is that it is a class/module. So you can inherit from the alias class or mixin the alias modules.

class MyHash < HashWithIndifferentAccess
end

The type definition corresponds to the following Ruby code that defines a constant.

HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess

Add use syntax

The spec: https://hackmd.io/@soutaro/rJ6CqDQss

The use syntax also defines alias names of type names, but unlike the class alias syntax, no constant is defined and it works on per-file basis.

use RBS::TypeName
use RBS::Namespace as NS
use RBS::AST::Declarations::*

With the directives, you can use TypeName for ::RBS::TypeName, NS for ::RBS::Namespace, and all types names under ::RBS::AST::Declarations with unqualified names.

This is an RBS specific feature that has no corresponding Ruby code. This helps keeping your type signatures compact and clean.

RBS collection skips loading application gems

Both libraries and applications are bundled with Bundler -- libraries are loaded in your application, but apps are not. Apps are executed in different process, and your Ruby code doesn't depends the classes/modules of the app dependencies.

RBS collection now skips loading RBS files of app dependencies, which is identified if it's declared with require: false in Gemfile.

gem 'steep', require: false        # RBS collection assumes that Steep is an application

If you have an application dependency without require: false, you can add an entry in rbs_collection.yaml.

gems:
  - name: steep
    ignore: true   # Explicitly ignore the dependency

It's the same with the other side. If you want to include the RBS of an require: false dependency, you can add an entry in rbs_collection.yaml to load it.

gems:
  - name: steep    # Explicitly declare the dependency, without ignoring it

To upgrade to the latest setup, edit the Gemfile and rbs_collection.yaml, run $ rbs collection update, and commit the updated rbs_collection.lock.yaml.

Upgrade guide 💪

RBS 3.0 has several breaking changes. This section explains the overview of the incompatibilities to help you making your Ruby code work with 3.0.

AST changes

For class/module alias

  • RBS::AST::Declarations::Alias is now renamed to TypeAlias
  • RBS::AST::Declarations::ClassAlias and RBS::AST::Declarations::ModuleAlias are added
  • RBS::AST::Declarations::t now has ClassAlias and ModuleAlias

For use syntax

  • RBS::AST::Directives is added for use directive

For per-method-overload annotations

  • RBS::AST::Members::MethodDefinition::Overload is added
  • RBS::AST::Members::MethodDefinition#method_types is renamed to #overloads
  • RBS::AST::Members::MethodDefinition#overload? is renamed to #overloading?

Parser method type

  • The deprecated overloadings with line: and column: keywords of RBS::Parser.parse_method_type and RBS::Parser.parse_type are deleted
  • RBS::Parser.parse_signature now returns a triple of RBS::Buffer, Array[RBS::AST::Directives::t], and Array[RBS::AST::Declarations::t]
  • RBS::EnvironmentLoader#each_signature is added, and #each_decl is deleted

RBS::Environment utilities

  • RBS::Environment::ModuleEntry and RBS::Environment::ClassEntry are added, replacing usages of MultiEntry[T]
  • RBS::Environment::ModuleAliasEntry, RBS::Environment::ClassAliasEntry, RBS::Environment::InterfaceEntry, RBS::Environment::ConstantEntry, and RBS::Environment::GlobalEntry are added, replacing usage of SingleEntry[N, T]
  • RBS::Environment#add_signature is introduced to support use directives, you can use the method instead of #<<
  • RBS::Environment#buffers_decls is moved to RBS::Environment#signatures
  • Many utility methods are added, like module_name?, constant_entry, ... Use those methods instead of directly accessing the internal data structures like #class_decls and #type_alias_decls (renamed from #alias_decls)