Crystal: mistaken “no overload matches”

Created on 25 Sep 2016  Â·  7Comments  Â·  Source: crystal-lang/crystal

I'm maintaining https://github.com/chenkovsky/docopt.cr 。after upgrading to 0.19.X, I find compiler complains "no overload matches". but when I remove the types from init function, it compiles.
I try to find a smaller example, but failed. sorry.

my code looks like that

class MyClass
....
@name : (String | Nil)
@value : (Nil | String | Int32 | Bool | Array(String))
 def initialize(@name : (String | Nil), @value : (Nil | String | Int32 | Bool | Array(String)) = nil)
# def initialize(@name, @value = nil) # if I use this function, it compiles.
....
end
bug compiler

Most helpful comment

Reduced:

class Gen(T)
end

class Sub < Gen(String)
end

def foo(x : Gen(String))
end

foo(Gen(String).new.as(Gen(String)))

All 7 comments

@chenkovsky:
What kind of benefits are you looking for, declaring the types in the body of the class and in the constructor?

This similar code works

class MyClass
@name : (String | Nil)
@value : (Nil | String | Int32 | Bool | Array(String))
  def initialize(@name = nil, @value = nil)
    pp @name
  end
end

MyClass.new name: "test"
# MyClass.new name: 1  => This doesn't compile because instantiation of @name Class variable doesn't allow Int32 type 

@chenkovsky:
I could not replicate this issue in the play.crystal-lang.org environment.
https://play.crystal-lang.org/#/r/1atz

@raydf , the code just shows where the compiler complains. it's not the simplest case that you can replicate this issue(I try to find one, but failed). If you want to replicate this issue. please checkout the repo https://github.com/chenkovsky/docopt.cr, and apply the patch. then run crystal spec

patch.txt

@chenkovsky
In the shard code i replicated the error, maybe someone else could reduce the code further.

Just as additional information using aliases for the union types in the constructor method, works correct:

    alias NameType = (String | Nil)
    alias ValueType = (Nil | String | Int32 | Bool | Array(String)) 
    getter name : NameType
    property value : ValueType

    def initialize(@name : NameType, @value : ValueType = nil)
      @children = nil.as(Array(Pattern) | Nil)
    end

in my another project, compiler always complain.

no overload matches 'MyClass.new' with type Array(String)+
Overloads are:

  • MyClass.new(param : Array(String))
    Couldn't find overloads for these types:
  • MyClass.new(Array(String))

i think these are the same bug.

@chenkovsky can you provide a sample code on how MyClass is being initialized?

Reduced:

class Gen(T)
end

class Sub < Gen(String)
end

def foo(x : Gen(String))
end

foo(Gen(String).new.as(Gen(String)))
Was this page helpful?
0 / 5 - 0 ratings

Related issues

will picture will  Â·  3Comments

costajob picture costajob  Â·  3Comments

ArthurZ picture ArthurZ  Â·  3Comments

cjgajard picture cjgajard  Â·  3Comments

nabeelomer picture nabeelomer  Â·  3Comments