Skip to content

Release Note 1.1

Soutaro Matsumoto edited this page Jul 31, 2022 · 7 revisions

Steep 1.1.1 is the latest version of Steep 1.1.

Some of the highlights in Steep 1.1 are:

  1. Type refinement with method calls (#590)
  2. Better multiple assignment type checking (#605)
  3. Fixing various generics problems

You can install it with $ gem install steep or using bundler.

gem 'steep', '~> 1.1.1'

See the CHANGELOG for the details.

Type narrowing on method calls #590

This has been one of the most frequently requested feature.

Steep has detected a type error from the code.

account = Account.find(email)                 # Assume `Account#phone` has a type of `String?`

if account.phone                              # Ensure that `#phone` is a `String`
  send_sms_to(
    "+81" + account.phone.delete_prefix("0")  # Type error detected because `#phone` may be changed since the last `if` test
  )
end

account.phone is a method call and it may return different values among calls. The sound/correct/safe analysis cannot assume it returns the same value on next call.

Steep is trying to relax the limitation. Steep assumes a method call will return the same value if it detect it is pure.

pure is a concept related to Pure function, and defined as follows in Steep:

  • Syntactic values, literals, variables, and lambdas, are pure
  • Method calls without block are pure if:
    • All of the receiver and arguments are pure, and
    • All of the methods the method call may invoke are pure
      • Attribute reading methods declared with attr_reader and attr_accessor in RBS are pure
      • Methods with %a{pure} annotation are pure

So, the Ruby code above will work if the #phone method is defined by attr_??? syntax or with %a{pure} annotation.

class Account
  attr_reader phone: String?        # `#phone` is _pure_

  attr_accessor phone: String?      # `#phone` is _pure_ (`#phone=` is not)

  %a{pure}
  def phone: () -> String?          # This is also _pure_ because of `%a{pure}` annotation
end

Note that there is no validation, enforcement, or proof that the implementations of pure methods are actually pure. You may define your custom implementation of #phone method even if it is defined by attr_reader in RBS. Another thread may change the value of @phone. It's an assumption defined in RBS to make your coding easier.

New Ruby diagnostic

  • Ruby::UnknownInstanceVariable is introduced for unknown instance variables
  • Ruby::UnknownGlobalVariable is introduced for unknown global variables
  • Ruby::MultipleAssignmentConversionError is introduced for the case #to_a or #to_ary is defined and doesn't return Array
Clone this wiki locally