I'm seeing some unexpected behaviour setting up RBS types on an existing Ruby project. A minimal example:
# lib/a.rb
class A
def self.foo
new
end
end
class B < A
def self.foo
super
end
end
puts A.foo.inspect
puts B.foo.inspect
Output
#<A:0x000055f7cfb03908>
#<B:0x000055f7cfb037f0>
Signature
# lib/a.rbs
class A
def self.foo: () -> A
end
class B < A
def self.foo: () -> B
end
but the steep type-checker gives me errors
lib/a.rb:8:11: [error] Cannot allow method body have type `::A` because declared as type `::B`
│ ::A <: ::B
│ ::Object <: ::B
│ ::BasicObject <: ::B
│
│ Diagnostic ID: Ruby::MethodBodyTypeMismatch
│
└ def self.foo
~~~
Is this an issue with steep or (more likely) my understanding of the Ruby typing syntax?
Is this an issue with steep or (more likely) my understanding of the Ruby typing syntax?
I believe it is neither.
Your syntax is perfectly fine (otherwise steep would not even be able to parse the RBS file and give you a syntax error) and I also don't see any problem with steep here. The code you have is genuinely type-unsafe according to the types you have declared:
B::foo
is declared to return an instance of B
B::foo
returns super
super
is A::foo
A::foo
is declared to return an instance of A
B::foo
is declared to return an instance of B
but it actually returns an instance of A
.Since A
is not convertible to B
, this is not type-safe.