Abstract def inside module not being enforced

I’m running into something that is a little confusing for me, so I was wondering if anyone could provide clarification. I have the following code:

module MyInterface
  abstract def do_something : String
end

class MyClient
  include MyInterface
  
  def do_something
    5
  end
end

client = MyClient.new
p client.do_something

This code compiles fine, but it is my understanding that it should not because the do_something signature inside MyClient does not match the abstract def. However, if I modify the abstract def to take any parameter, it gets enforced ie. do_something(num : Int32) : String

Is this expected behavior? If so, what am I missing? Does the return type have to be explicitly given?

With the current release this is how it works. https://github.com/crystal-lang/crystal/pull/7956 was merged recently, but being changed to a warning for now. Which would tell you like

Warning: this method must return String, which is the return type of the overwritten
method MyClient#do_something(), or a subtype of it, not Int32

Great, thanks for the info :+1:

Above code running error now, it’s expected.

 8 | def do_something
         ^-----------
Error: this method overrides MyInterface#do_something() which has an explicit return type of String.

Please add an explicit return type (String or a subtype of it) to this method as well.