crystal-lang / crystal

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

BUG: trying to upcast #11786

Open wonderix opened 2 years ago

wonderix commented 2 years ago

When I try to run shards install && crystal spec on the project crystal-tds (branch crystal-bug) I get

BUG: trying to upcast TDS::Parameter (Crystal::NonGenericClassType) <- (TDS::Bit | TDS::Datetime | TDS::Datetime_4 | TDS::Datetime_n | TDS::Decimal | TDS::Flt_4 | TDS::Flt_8 | TDS::Flt_n | TDS::Image | TDS::Int_1 | TDS::Int_2 | TDS::Int_4 | TDS::Int_8 | TDS::Int_n | TDS::NText | TDS::NVarchar | TDS::Null | TDS::SInt_1 | TDS::Text | TDS::UInt_2 | TDS::UInt_4 | TDS::UInt_8 | TDS::UInt_n | TDS::UniqueIdentifier | TDS::Varchar) (Crystal::MixedUnionType) (Exception)
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'raise<Exception>:NoReturn'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'raise<String>:NoReturn'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#upcast_distinct<LLVM::Value, Crystal::Type+, Crystal::Type+>:NoReturn'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#upcast<LLVM::Value, Crystal::Type+, Crystal::Type+>:LLVM::Value'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor::Phi#add<LLVM::Value, Crystal::Type+, Bool>:(LLVM::Value | Nil)'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool'
  from /opt/homebrew/Cellar/crystal/1.3.2/libexec/crystal in 'Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor> ...

with crystal -v

Crystal 1.3.2 (2022-01-18)

LLVM: 13.0.0
Default target: aarch64-apple-darwin21.1.0

Unfortunately, I was not able to reduce the code. I found several other bugs which look similar but not exactly like this one. The same code was working with older versions of crystal (e.g. 1.0).

wonderix commented 2 years ago

I managed to reduce the problem to the following code

require "db"

module TDS
  abstract struct TypeInfo
  end

  struct Int_n < TypeInfo
  end

  class PreparedStatement < DB::Statement
    @type_infos = [] of TypeInfo

    def initialize(connection, command)
      super(connection, command)
    end

    protected def perform_query(args : Enumerable) : DB::ResultSet
      raise "not implemented"
    end

    def perform_exec(args : Enumerable) : DB::ExecResult
      parameters = args.zip(@type_infos).map do |x|
        test(x[0].as(Int32), type_info: x[1].as(TypeInfo))
      end
      raise "not implemented"
    end

    def test(@value : Int32, type_info : TypeInfo? = nil, @name = "") 
    end
  end
end

DB.open("/test").exec("CREATE DATABASE test")
y8 commented 2 years ago

I think I'm hitting the same issue, but with BUG: trying to downcast ...

I was able to narrow issued down to this test case (https://play.crystal-lang.org/#/r/cptv)

abstract struct Root; end
abstract struct Alpha < Root; end
abstract struct Bravo < Root; end

abstract struct Uno < Alpha; end
abstract struct Duo < Bravo; end

alias BadUnion = (Alpha | Bravo)

struct KillCompiler
  property bad_one = [] of BadUnion
end

pp KillCompiler.new

For some reason it compiles without both Uno and Duo.

I suppose BadUnion is a mistake, since there is no implementations of those abstract types? But anyways, that should not crash the compiler.

wonderix commented 2 years ago

I faced the same issue in a different project again today.

alexandrio commented 2 years ago

Hi, just playing with minimal sample to connect to sql server 2014 is generating same error:

crystal --version
Crystal 1.5.0 [994c70b10] (2022-07-06)

LLVM: 10.0.0
Default target: x86_64-unknown-linux-gnu
-------------------------------------------------------------------------------------
tsql -C
Compile-time settings (established with the "configure" script)
Version: freetds v1.3.6
freetds.conf directory: /etc/freetds
MS db-lib source compatibility: no
Sybase binary compatibility: yes
Thread safety: yes
iconv library: yes
TDS version: auto
iODBC: no
unixodbc: yes
SSPI "trusted" logins: no
Kerberos: yes
OpenSSL: no
GnuTLS: yes
MARS: yes
---------------------------------------------------------------------------------

Source code:


require "db"
require "tds"

module Tutorial
  VERSION = "0.1.0"

// connection string info ommited

  DB.open "tds://userlogin:password@serverip:port/database" do |db|
    # ... use db to perform queries
    db.query "select Id, name from names" do |rs|
      rs.each do
        Id = rs.read(String)
        name = rs.read(String)
        puts "#{Id} - #{name}"
      end
    end
  end
end

table info:

table: names Id char(20) pk name char(50)

result:

BUG: trying to upcast TDS::Parameter (Crystal::NonGenericClassType) <- (TDS::Bit | TDS::Datetime | TDS::Datetime_4 | TDS::Datetime_n | TDS::Decimal | TDS::Flt_4 | TDS::Flt_8 | TDS::Flt_n | TDS::Image | TDS::Int_1 | TDS::Int_2 | TDS::Int_4 | TDS::Int_8 | TDS::Int_n | TDS::NText | TDS::NVarchar | TDS::Null | TDS::SInt_1 | TDS::Text | TDS::UInt_2 | TDS::UInt_4 | TDS::UInt_8 | TDS::UInt_n | TDS::UniqueIdentifier | TDS::Varchar) (Crystal::MixedUnionType) (Exception)
  from /crystal/src/compiler/crystal/codegen/cast.cr:668:5 in 'upcast_distinct'
  from /crystal/src/compiler/crystal/codegen/cast.cr:523:15 in 'upcast'
  from /crystal/src/compiler/crystal/codegen/phi.cr:64:11 in 'add'
  from /crystal/src/compiler/crystal/codegen/phi.cr:12:7 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'prepare_call_args_non_external'
  from /crystal/src/compiler/crystal/codegen/call.cr:57:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/types.cr:8:12 in 'prepare_call_args_non_external'
  from /crystal/src/compiler/crystal/codegen/call.cr:57:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'prepare_call_args_non_external'
  from /crystal/src/compiler/crystal/codegen/call.cr:57:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'codegen_fun'
  from /crystal/src/compiler/crystal/codegen/fun.cr:51:3 in 'target_def_fun'
  from /crystal/src/compiler/crystal/codegen/call.cr:454:5 in 'visit'
  from /crystal/src/compiler/crystal/semantic/bindings.cr:17:7 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/exception.cr:92:7 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'codegen_fun'
  from /crystal/src/compiler/crystal/codegen/fun.cr:51:3 in 'target_def_fun'
  from /crystal/src/compiler/crystal/codegen/call.cr:454:5 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'codegen_fun'
  from /crystal/src/compiler/crystal/codegen/fun.cr:51:3 in 'target_def_fun'
  from /crystal/src/compiler/crystal/codegen/call.cr:454:5 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/exception.cr:92:7 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'codegen_fun'
  from /crystal/src/compiler/crystal/codegen/fun.cr:51:3 in 'target_def_fun'
  from /crystal/src/compiler/crystal/codegen/call.cr:454:5 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2279:7 in 'codegen_fun'
  from /crystal/src/compiler/crystal/codegen/fun.cr:51:3 in 'target_def_fun'
  from /crystal/src/compiler/crystal/codegen/call.cr:454:5 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:72:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/exception.cr:92:7 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2274:9 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:725:15 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:665:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2244:7 in 'codegen'
  from /crystal/src/compiler/crystal/compiler.cr:173:16 in 'compile'
  from /crystal/src/compiler/crystal/command.cr:215:5 in 'run_command'
  from /crystal/src/compiler/crystal/command.cr:64:5 in '__crystal_main'
  from /crystal/src/crystal/main.cr:115:5 in 'main'
  from src/env/__libc_start_main.c:94:2 in 'libc_start_main_stage2'
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
straight-shoota commented 2 years ago

There is definitely an error in your code because Id is a constant and you use it like a variable, assigning values repeatedly. Ypi can't declare constants dynamically.

This should definitely trigger a compiler error. Apparently there is some other bug in the compiler that prevents it from even reaching this point.