Skip to content

Release Note 1.8

Soutaro Matsumoto edited this page Sep 18, 2024 · 4 revisions

Some of the highlights in Steep 1.8 are:

  • Generics improvements (#1216, #1220)
  • Fix subtyping on tuples/records (#1221)
  • Support optional keys in record types (#1223)
  • Ignore type assertions for compatibility with rbs-inline (#1179, #1176)

You can install it with $ gem install steep --pre or using Bundler.

gem 'steep', require: false, '~> 1.8.0.pre'

See the CHANGELOG for the details.

Generics improvements

PRs: #1216, #1220

RBS 3.6 ships with a few major improvements on generics, and Steep 1.8 supports the improved generics.

(We had planned to add an implicit upper bound to type variables, but it was reverted due to unexpected complexity around void types.)

Fix subtyping on tuples/records

PR: #1221

Tuples was not a subtype of Object, but it is now.

tuple = [1, ""] #: [Integer, String]
object = tuple #: Object

Support optional keys in record types

PR: #1223

Optional keys in record types are supported in Steep. The optional keys are the keys that may be absent in the Hash.

# @type var record: { id: Integer, ?name: String }

record = { id: 123, name: "Soutaro" }   # OK
record = { id: 123 }                    # OK because name is optional

Note that this causes an unsoundness. We are carefully watching if the unsoundness is acceptable or not.

record1 = { id: 123, name: "Soutaro" } #: { id: Integer, name: String }

# Assigning the record by dropping the name key is allowed
record2 = record1 #: { id: Integer }

# Assigning the record by adding optional key is allowed
record3 = record2 #: { id: Integer, ?name: Integer }

# record3[:name] is Integer, but it's actually a String object. Resulting in a runtime type error.
record3[:name] + 1

Ignore type assertions for compatibility with rbs-inline

PRs: #1179, #1176

Type assertion on attr_reader family and def syntax is ignored to make it compatible with rbs-inline annotations.

class Foo
  # The type assertion in Steep means the type of `attr_reader` call is `Integer`,
  # while the same syntax in rbs-inline means the type of `id` attribute is `Integer`.
  # Then, the assertions on `attr_reader` (and likes) are ignored in Steep.
  attr_reader :id #: Integer

  # Same for `def` syntax.
  def to_s #: String
    "Foo"
  end
end