steep
steep copied to clipboard
Use of `Symbol#to_proc` leads to confusing errors.
Consider this ruby file:
class MyClass
def using_symbol_to_proc(array)
array.map(&:foo)
end
def using_a_block(array)
array.map { |e| e.foo }
end
end
...paired with this rbs file:
class MyClass
def using_symbol_to_proc: (::Array[::String]) -> void
def using_a_block: (::Array[::String]) -> void
end
When I run steep, it gives me different errors for the two usages of foo:
lib/my_class.rb:3:4: [error] Cannot find compatible overloading of method `map` of type `::Array[::String]`
│ Method types:
│ def map: [U] () { (::String) -> U } -> ::Array[U]
│ | () -> ::Enumerator[::String, ::Array[untyped]]
│
│ Diagnostic ID: Ruby::UnresolvedOverloading
│
└ array.map(&:foo)
~~~~~~~~~~~~~~~~
lib/my_class.rb:7:22: [error] Type `::String` does not have method `foo`
│ Diagnostic ID: Ruby::NoMethod
│
└ array.map { |e| e.foo }
~~~
Detected 2 problems from 1 file
The second one is very clear: String doesn't have a foo method.
The first error is quite confusing: it makes it sound like Array#map isn't properly defined in RBS or something. It's not at all clear that the problem is that String lacks a foo method.
Symbol#to_proc is a very common idiom in Ruby, particularly for Enumerable#map, etc, and steep would be friendlier to use if it provided the same error in this situation. Conceptually, I think of some_method(&:foo) and some_method { |e| e.foo } as being equivalent, so it's quite unexpected that steep treats them differently.