crystal-lang / crystal

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

Crash when using try {..} to guard against nilable type #10550

Open Smarre opened 3 years ago

Smarre commented 3 years ago

Using try { .. } to guard against type that may a value or nil causes an error to be thrown:

> crystal build minimal.cr
BUG: called create_llvm_type for I (Exception)
  from /crystal/src/compiler/crystal/codegen/llvm_typer.cr:254:7 in 'create_llvm_type'
  from /crystal/src/pointer.cr:117:6 in 'llvm_type'
  from /crystal/src/compiler/crystal/codegen/unions.cr:34:28 in 'create_llvm_type'
  from /crystal/src/compiler/crystal/codegen/llvm_typer.cr:90:26 in 'llvm_type'
  from /crystal/src/compiler/crystal/codegen/llvm_typer.cr:84:5 in 'alloca_non_closured_vars'
  from /crystal/src/compiler/crystal/codegen/call.cr:282:7 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/codegen.cr:768:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/context.cr:74:5 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2179:9 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/codegen.cr:619:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2184: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:445:5 in 'visit'
  from /crystal/src/compiler/crystal/syntax/visitor.cr:27:12 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:619:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2149:7 in 'codegen'
  from /crystal/src/compiler/crystal/compiler.cr:172:16 in 'compile'
  from /crystal/src/compiler/crystal/command.cr:296:3 in 'run'
  from /crystal/src/compiler/crystal.cr:11:1 in '__crystal_main'
  from /crystal/src/crystal/main.cr:110: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

I can reproduce the bug with following code:

class TestClass
  property excluded : Hash(String, Array) | Nil

  def run
    key = ""
    value = ""

    @excluded.try do |excluded|
      unless excluded[key].nil?
        excluded[key].each do |excluded_value|
          # This block seems to be causing the crash.
        end
      end
    end
  end
end

test = TestClass.new
test.run

Crystal version:

Crystal 1.0.0 [dd40a2442] (2021-03-22)

LLVM: 10.0.0
Default target: x86_64-unknown-linux-gnu
HertzDevil commented 3 years ago

The snippet seems not to break when Array has a generic type argument.

I don't think @excluded : Hash(String, Array) | Nil should ever compile, for the same reason you cannot do x = uninitialized Hash(String, Array) | Nil.

Smarre commented 3 years ago

Yes, though I’d expect to have some better error than that stack trace.

straight-shoota commented 3 years ago

Definitely! The bug is that restricting an ivar to Hash(String, Array) | Nil should be a proper compiler error. The rest is secondary.

HertzDevil commented 3 years ago

Might be related to #3770.