steep
steep copied to clipboard
`steep check` uses wrong context for `#define_method` in a singleton
Here is example:
# storage.rb
class Storage
attr_reader :store
def initialize
@store = {}
end
class << self
def dynamic_attr(name)
define_method(name) do
store[name]
end
define_method(:"#{name}=") do |val|
store[name] = val
end
end
end
end
# storage.rbs
class Storage
attr_reader store: Hash[Symbol, untyped]
def initialize: () -> void
def self.dynamic_attr: (Symbol name) -> void
end
❯ steep check
storage.rb:11:8: [error] Type `singleton(::Storage)` does not have method `store`
│ Diagnostic ID: Ruby::NoMethod
│
└ store[name]
~~~~~
storage.rb:15:8: [error] Type `singleton(::Storage)` does not have method `store`
│ Diagnostic ID: Ruby::NoMethod
│
└ store[name] = val
~~~~~
I think I'm having a similar error with Sequel:
class Game < Sequel::Model
# other code
dataset_module do
def current
where(status: 'init').first
end
end
end
And no matter how I try to define dataset_module, I get this error:
lib/models.rb:22:6: [error] Type `::Game` does not have method `where`
│ Diagnostic ID: Ruby::NoMethod
│
└ where(status: 'init').first
~~~~~
Thank you for reporting the problem. Will take a look at the context setup if it can be supported.
A workaround is using @type self: Storage annotation inside the block given to define_method.
I'm not sure what the self is inside dataset_module, but @type self: T or @implements annotation might help you...