steep
steep copied to clipboard
steep has totally wrong scope in class_eval
When a module augments some class's functionality via class_eval
, steep appears to completely overlook the fact that inside class_eval
, self
is the target class and not the module that contains the augmenting logic. Example:
class Base
def self.foo
puts 'hello foo'
end
end
module Mod
def self.augment(base)
base.class_eval do
foo
end
end
end
Mod.augment(Base)
sig:
class Base
def self.foo: () -> untyped
end
module Mod
def self.augment: (untyped base) -> untyped
end
The above code executes and prints "hello foo", but fails steep check:
class_eval.rb:10:6: [error] Type `singleton(::Mod)` does not have method `foo`
│ Diagnostic ID: Ruby::NoMethod
│
└ foo
~~~
Note that steep tries to find foo
on Mod
which is totally incorrect.
Conversely, steep is perfectly happy with the following code and type definition:
class Base2
end
module Mod2
def foo
puts 'hello foo'
end
def self.augment(base)
base.class_eval do
foo
end
end
end
Mod2.augment(Base2)
class Base2
end
module Mod2
def self.augment: (untyped base) -> untyped
def foo: () -> untyped
end
Here, I put foo
into the module. But, obviously, the above is not valid Ruby:
% ruby class_eval_2.rb
class_eval_2.rb:11:in `block in augment': undefined local variable or method `foo' for class Base2 (NameError)
foo
^^^
from class_eval_2.rb:10:in `class_eval'
from class_eval_2.rb:10:in `augment'
from class_eval_2.rb:16:in `<main>'