crystal icon indicating copy to clipboard operation
crystal copied to clipboard

Bug: Nil assertion failed (NilAssertionError)

Open LoadingBG opened this issue 2 years ago • 0 comments

The following code:

alias RecType = Int32 | Array(RecType)

Proc(NamedTuple(value: Int32 | RecType)?).new do
  next {value: 1} if false
  Proc(NamedTuple(value: RecType)?).new {}.call
end

produces this output:

Nil assertion failed (NilAssertionError)
  from /crystal/src/nil.cr:108:5 in 'not_nil!'
  from /crystal/src/compiler/crystal/codegen/cast.cr:588:29 in 'upcast_distinct'
  from /crystal/src/compiler/crystal/codegen/cast.cr:523:15 in 'upcast'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:709:17 in 'codegen_return'
  from /crystal/src/compiler/crystal/codegen/fun.cr:229:5 in 'codegen_fun'
  from /crystal/src/compiler/crystal/codegen/fun.cr:51:3 in 'accept'
  from /crystal/src/compiler/crystal/codegen/call.cr:331: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: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

Not using a recursive type alias:

Proc(NamedTuple(value: Int32 | String)?).new do
  next {value: 1} if false
  Proc(NamedTuple(value: String)?).new {}.call
end

is perfectly fine, as is not using NamedTuple:

alias RecType = Int32 | Array(RecType)

Proc(Box(Int32 | RecType)?).new do
  next Box.new(1) if false
  Proc(Box(RecType)?).new {}.call
end

(probably has something to do with **T) Also making the proc return non-nil value (removing the ?) produces no error.

Line 4 is there to make the compiler happy but if if false is removed, no error occurs.

If the union type of value includes a type not in the definition of the recursive type, no error occurs:

alias RecType = Int32 | Array(RecType)

Proc(NamedTuple(value: String | RecType)?).new do
  next {value: 1} if false
  Proc(NamedTuple(value: RecType)?).new {}.call
end # No errors
alias RecType = String | Int32 | Array(RecType)

Proc(NamedTuple(value: String | RecType)?).new do
  next {value: 1} if false
  Proc(NamedTuple(value: RecType)?).new {}.call
end # Nil assertion error
alias RecType = String | Int32 | Array(RecType)

Proc(NamedTuple(value: String | Int32 | RecType)?).new do
  next {value: 1} if false
  Proc(NamedTuple(value: RecType)?).new {}.call
end # Also a nil assertion error

And the alias doesn't have to be a union:

alias RecType = Array(RecType)

Proc(NamedTuple(value: Array(RecType) | RecType)?).new do
  next {value: [] of RecType} if false
  Proc(NamedTuple(value: RecType)?).new {}.call
end # A nil assertion error yet again

However, not using a union does not produce an error:

alias RecType = Int32 | Array(RecType)

Proc(NamedTuple(value: RecType)?).new do
  next {value: 1} if false
  Proc(NamedTuple(value: RecType)?).new {}.call
end # No errors

Crystal version:

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

LLVM: 10.0.0
Default target: x86_64-unknown-linux-gnu

Running on Ubuntu 20.04 on WSL 2 on Windows 10 (I was able to reproduce the examples on play.crystal-lang.org as well)

LoadingBG avatar Aug 10 '22 15:08 LoadingBG