-
Notifications
You must be signed in to change notification settings - Fork 89
Release Note 1.1
Steep 1.1.1
is the latest version of Steep 1.1.
Some of the highlights in Steep 1.1 are:
- Type refinement with method calls (#590)
- Better multiple assignment type checking (#605)
- 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
andattr_accessor
in RBS are pure - Methods with
%a{pure}
annotation are pure
- Attribute reading methods declared with
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.
-
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