Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{"a", "b"}.as Enumerable(String) crashes the compiler #8771

Open
aljelly opened this issue Feb 9, 2020 · 3 comments
Open

{"a", "b"}.as Enumerable(String) crashes the compiler #8771

aljelly opened this issue Feb 9, 2020 · 3 comments
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler:generics

Comments

@aljelly
Copy link

aljelly commented Feb 9, 2020

Code:

{"a", "b"}.as Enumerable(String)

Result:

Nil assertion failed (NilAssertionError)
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from main
  from __libc_start_main
  from _start
  from ???
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

Playground link

Version:

$ crystal -v
Crystal 0.32.1 [41bd18fbe] (2019-12-18)

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

It specifically seems to be with Tuple(String) when the tuple has more than one string. {1, 2}.as Enumerable(Int32) does not crash the compiler, nor does {"a"}.as Enumerable(String).

@aljelly aljelly changed the title {"a", "b"}.as(Enumerable(String)) crashes the compiler {"a", "b"}.as Enumerable(String) crashes the compiler Feb 9, 2020
@jhass jhass added kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler labels Feb 9, 2020
@rdp
Copy link
Contributor

rdp commented Feb 10, 2020

Not sure why the line numbers aren't showing up. Huh?

On OS X:

$ crystal -v
Crystal 0.32.1 (2019-12-18)

LLVM: 9.0.0
Default target: x86_64-apple-macosx
$ crystal eval '{"a", "b"}.as Enumerable(String)'
Nil assertion failed (NilAssertionError)
  from Nil#not_nil!:NoReturn
  from Crystal::CodeGenVisitor#upcast_distinct<LLVM::Value, Crystal::MixedUnionType, Crystal::Type+>:LLVM::Value
  from Crystal::CodeGenVisitor#upcast<LLVM::Value, Crystal::Type+, Crystal::Type+>:LLVM::Value
  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#eval:NoReturn
  from Crystal::Command#run:(Bool | Crystal::Compiler::Result | Nil)
  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

@evvo
Copy link

evvo commented Feb 18, 2020

These works (Crystal 0.32.1) - the problem seems to happen only when there are 2 elements - the compiler somehow assumes that one of the elements could be a Nil:

{"a", "b", "c"}.as Enumerable(String)
{"a"}.as Enumerable(String)
{"a", "b"}.to_a.as Enumerable(String)
{"a", "b", "c", "d"}.as Enumerable(String)
{"a", "b", "c", "d", "e"}.as Enumerable(String)

alias StringNil = String | Nil
{"a", "b"}.as Enumerable(StringNil)

https://carc.in/#/r/8kwv

@rdp , the line numbers are not showing properly for me as well (Ubuntu 16.04, Crystal 0.33.0 [612825a] (2020-02-14)):

$ crystal eval '{"a", "b"}.as Enumerable(String)'
Nil assertion failed (NilAssertionError)
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
  from ???
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

@HertzDevil
Copy link
Contributor

Reduced:

# `Tuple` (built-in type declared by `Crystal::Program`)
struct Foo(*T)
end

# `ENV` (src/env.cr)
module Bar
  extend Enumerable(Foo(String, String))
end

# `Tuple` (src/tuple.cr, this file is required after src/env.cr)
struct Foo(*T)
  include Enumerable(Union(*T))
end

def foo
  Foo(String, String).new.as(Enumerable(String))
  {% p Enumerable(String).includers %} # => [] of ::NoReturn
end

foo
BUG: trying to upcast Enumerable(String) (Crystal::GenericModuleInstanceType) <- Foo(String) (Crystal::GenericClassInstanceType) (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/codegen.cr:1310:11 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:667:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2246:7 in 'codegen'
  from /crystal/src/compiler/crystal/compiler.cr:173:16 in 'compile'
  from /crystal/src/compiler/crystal/command.cr:220: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'

Foo(String, String) is not registered as an includer of Enumerable(String), which breaks codegen. The particular variant of the error in the OP happens when Foo is Tuple or NamedTuple and when some reference type also includes Enumerable:

module Bar
  extend Enumerable({String, String})
end

struct Tuple(*T)
  include Enumerable(Union(*T))
end

class Foo2
  include Enumerable(String)
end

def foo
  {"a"}.as(Enumerable(String))
  {"a", "b"}.as(Enumerable(String))
  {% p Enumerable(String).includers %} # => [Foo2, Tuple(String)]
end

foo
Nil assertion failed (NilAssertionError)
  from /crystal/src/nil.cr:108:5 in 'not_nil!'
  from /crystal/src/compiler/crystal/codegen/cast.cr:636:27 in 'upcast_distinct'
  from /crystal/src/compiler/crystal/codegen/cast.cr:523:15 in 'upcast'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:1310:11 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:667:9 in 'accept'
  from /crystal/src/compiler/crystal/codegen/codegen.cr:2246:7 in 'codegen'
  from /crystal/src/compiler/crystal/compiler.cr:173:16 in 'compile'
  from /crystal/src/compiler/crystal/command.cr:220: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'

Related: #10518

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind:bug A bug in the code. Does not apply to documentation, specs, etc. topic:compiler:generics
Projects
None yet
Development

No branches or pull requests

5 participants