Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restrict refute_send_type to check method call doesn't match with type #588

Conversation

pocke
Copy link
Member

@pocke pocke commented Feb 7, 2021

This pull request adds a more strict check with refute_send_type.

Problem

I think refute_send_type assertion isn't enough to check the type mismatch.

Currently, refute_send_type checks that the method call raises an error, and the method call is matched with the method_type that is specified as an argument of refute_send_type. But the RBS, which is exposed to the end-users, doesn't affect refute_send_type. So it checks nothing about the RBS, but it checks the implementation.

I think refute_send_type should check the RBS, so the current behavior is not enough as a test assertion.

Solution

Check that the RBS declines the method call.

ref: #586 (comment)

@pocke pocke mentioned this pull request Feb 7, 2021
@pocke pocke force-pushed the Restrict__refute_send_type__to_check_method_call_doesn_t_match_with_type branch from 20cf3b1 to e1b2b36 Compare February 7, 2021 07:39
@pocke pocke marked this pull request as ready for review February 7, 2021 09:44
@@ -1736,7 +1736,7 @@ class Array[unchecked out Elem] < Object
# See also Enumerable#sort_by.
#
def sort: () -> ::Array[Elem]
| () { (Elem a, Elem b) -> ::Integer? } -> ::Array[Elem]
| () { (Elem a, Elem b) -> ::Integer } -> ::Array[Elem]
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Array#sort's block doesn't accept nil as the returned value actually, so I removed nil.

It is a more strict type, but it can be problematic with <=> method.
For example, Integer#<=> may return a nil when the values are incomparable. So the returned type is Integer?.

rbs/core/integer.rbs

Lines 108 to 115 in 26baa08

# Comparison---Returns -1, 0, or +1 depending on whether `int` is less than,
# equal to, or greater than `numeric`.
#
# This is the basis for the tests in the Comparable module.
#
# `nil` is returned if the two values are incomparable.
#
def <=>: (Numeric) -> Integer?

So Array#sort will not become to accept the following code by this change.

[1,2,3].sort { |a, b| a <=> b }

But personally I think Integer is better than Integer? as the returned value of sort's block. Array#sort always raises when the block returns nil.
And we can improves Integer#<=> type, like (Integer) => Integer | (Numeric) -> Integer?. The improvement will resolve the Array#sort's problem.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense. 👍

(I made it Integer? because of the return type of <=>.)

@soutaro
Copy link
Member

soutaro commented Feb 9, 2021

@pocke I'm not totally sure if this is the best way. But, I agree that type checking the calls with respect to RBS makes sense. Thanks!

@soutaro soutaro merged commit f965869 into ruby:master Feb 9, 2021
@pocke pocke mentioned this pull request Feb 10, 2021
@pocke pocke deleted the Restrict__refute_send_type__to_check_method_call_doesn_t_match_with_type branch February 10, 2021 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants