Crystal: X target defs for method (Exception)

Created on 12 Oct 2020  路  4Comments  路  Source: crystal-lang/crystal

Sample code to reproduce

abstract struct Parent
  abstract def work(a : Int32, b : Int32)
  def get
    ->work(Int32,Int32)
  end
end

struct Child1 < Parent
    def work(a : Int32, b : Int32)
      a + b
    end
end

struct Child2 < Parent
  def work(a : Int32, b : Int32)
    a - b
  end
end

pp [Child1.new,Child2.new].map(&.get)

Above code triggers below Compiler exception

2 target defs for work(arg0, arg1) (Exception)
  from raise<Exception>:NoReturn
  from raise<String>:NoReturn
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#codegen_fun<String, Crystal::Def+, Crystal::Type+, Bool, Crystal::CodeGenVisitor::ModuleInfo, Bool, Bool>:LLVM::Function
  from Crystal::CodeGenVisitor#target_def_fun<Crystal::Def+, Crystal::Type+>:LLVM::Function
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)
  from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
  from Crystal::Compiler#codegen<Crystal::Program, Crystal::ASTNode+, Array(Crystal::Compiler::Source), String>:(Tuple(Array(Crystal::Compiler::CompilationUnit), Array(String)) | Nil)
  from Crystal::Compiler#compile<Array(Crystal::Compiler::Source), String>:Crystal::Compiler::Result
  from Crystal::Command#run_command<Bool>:Nil
  from Crystal::Command#run:(Bool | Nil)
  from __crystal_main
  from main
Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues

Most helpful comment

As a workaround use ->self.work(Int32, Int32) on 1.0.0-dev

abstract struct Parent
  abstract def work(a : Int32, b : Int32)

  def get
    ->self.work(Int32, Int32)
  end
end

All 4 comments

is this a bug? or code logic is defeating the intention? Intention of raising this was to bring this (assumed bug) to light, but if this is intended behavior, then better close this issue to avoid false alarm.

It's a bug

To clarify a bit more, ->work(Int32,Int32) refers to a Proc that will have to do multiple dispatch over the Parent subclasses. But that (multidispatch) wasn't contemplated when we implemented procs so it's not working right. Ideally it should work but it's a bit hard to implement.

As a workaround use ->self.work(Int32, Int32) on 1.0.0-dev

abstract struct Parent
  abstract def work(a : Int32, b : Int32)

  def get
    ->self.work(Int32, Int32)
  end
end
Was this page helpful?
0 / 5 - 0 ratings

Related issues

RX14 picture RX14  路  3Comments

lbguilherme picture lbguilherme  路  3Comments

oprypin picture oprypin  路  3Comments

oprypin picture oprypin  路  3Comments

costajob picture costajob  路  3Comments