crystal-lang / crystal

The Crystal Programming Language
https://crystal-lang.org
Apache License 2.0
19.3k stars 1.61k forks source link

Abstract def overload with free var #14451

Open Blacksmoke16 opened 4 months ago

Blacksmoke16 commented 4 months ago

Given the following code:

class Foo; end

module TestInterface
  abstract def add(foo : Foo) : Foo
  abstract def add(bar : T) : Nil forall T
end

class Test
  include TestInterface

  def add(foo : Foo) : Foo
    foo
  end

  def add(bar : T) : Nil forall T

  end
end

t = Test.new

pp t.add Foo.new
pp t.add 123

It fails to compile due to:

 11 | def add(foo : Foo) : Foo
                           ^--
Error: this method must return Nil, which is the return type of the overridden method TestInterface#add(bar : T) forall T, or a subtype of it, not Foo

I also tried with -Dpreview_overload_order which resulted in the same error.

It seems the abstract def checker thinks the overload with the explicit type is overriding the free var overload, instead of treating them separately.

I was able to work around this for now by defining the free var method in the interface as:

def add(bar : T) : Nil forall T
  {% @type.raise "abstract `def TestInterface#add(bar : T) : Nil forall T` must be implemented by #{@type}" %}
end

Which works for now :shrug:.

HertzDevil commented 4 months ago

Duplicate of #10699?

Blacksmoke16 commented 4 months ago

I found that one, but the error in this one was different so reported it separately.