After upgrading to crystal 0.24.1 from 0.23.1 I can no longer compile the timuckun/crystal-liblmdb shard.
Here's the crystal -v output:
Crystal 0.24.1 (2018-01-27)
LLVM: 5.0.1
Default target: x86_64-apple-macosx
The compilation fails with the following error in src/lmdb/base.cr:112:16:
Error target prget failed to compile:
BUG: sizeof(typeof(x)) at /Users/felix/dev/misc/prget/lib/lmdb/src/lmdb/base.cr:112:16 should receive a type
Crystal::MainVisitor#visit<Crystal::SizeOf>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::Assign>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::If>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::If>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::Assign>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::Block>:(Bool | Nil)
Crystal::MainVisitor#visit<Crystal::Yield>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::ExceptionHandler>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::Assign>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#expand<Crystal::MultiAssign>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::Block>:(Bool | Nil)
Crystal::MainVisitor#visit<Crystal::Yield>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::ExceptionHandler>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::If>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::If>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Call#instantiate<Crystal::Matches, Crystal::Type+, Nil>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in_type<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil), Nil, String, Bool, Bool>:Array(Crystal::Def+)
Crystal::Call#lookup_matches_in<Crystal::Type+, Array(Crystal::Type+), (Array(Crystal::NamedArgumentType) | Nil)>:Array(Crystal::Def+)
Crystal::Call#recalculate:Nil
Crystal::MainVisitor#visit<Crystal::Call>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Program#visit_main<Crystal::ASTNode+, Crystal::MainVisitor, Bool, Bool>:Crystal::ASTNode+
Crystal::Program#semantic<Crystal::ASTNode+, Bool>:Crystal::ASTNode+
Crystal::Compiler#compile<Array(Crystal::Compiler::Source), String>:Crystal::Compiler::Result
Crystal::Command#run:(Bool | Crystal::Compiler::Result | IO::FileDescriptor | Nil)
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
The problem also occurs when cloning the shard and running crystal spec(you must have liblmdb installed, eg. using brew install lmdb on macOS).
I tried building a minimal reproduction, but the following code compiles fine on 0.24.1:
x = 1
case x
when Int32, UInt32, Float32, Int64, UInt64, Float64
size = sizeof(typeof(x))
puts size
end
I tested compilation using 0.24.0 and it works, so regression happened some time after 0.24.0.
This is still broken in 0.24.2.
Same problem with https://github.com/Papierkorb/cannon - works in 0.24.0, broken in 0.24.2, #5807 doesn't fix it.
BUG: sizeof(typeof(value)) at expanded macro: fast_encode:1:51 should receive a type
@konovod Have you been able to create a standalone test case?
Huh, i tried and looks like problem isn't so scary.
basically, test case is
v = nil
if v.nil?
#
else
sizeof(typeof(v))
end
in real code it happens because v is an input argument of a method, so usually it is a union or not nil, but sometimes it is called directly with nil.
I'm having the same problem using @konovod's snippet.
# tmp/bug.cr
v = nil
if v.nil?
#
else
sizeof(typeof(v))
end
crystal tmp/bug.cr
BUG: sizeof(typeof(v)) at /Users/scott.pierce/code/crystal/mandelbrot/tmp/bug.cr:5:3 should receive a type
Crystal::MainVisitor#visit<Crystal::SizeOf>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::MainVisitor#visit<Crystal::If>:Bool
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::MainVisitor>:Nil
Crystal::Program#visit_main<Crystal::ASTNode+, Crystal::MainVisitor, Bool, Bool>:Crystal::ASTNode+
Crystal::Program#semantic<Crystal::ASTNode+, Bool>:Crystal::ASTNode+
Crystal::Compiler#compile<Array(Crystal::Compiler::Source), String>:Crystal::Compiler::Result
Crystal::Command#run_command<Bool>:Nil
Crystal::Command#run:(Bool | Crystal::Compiler::Result | IO::FileDescriptor | Nil)
main
crystal --version
Crystal 0.24.2 (2018-03-10)
LLVM: 5.0.1
Default target: x86_64-apple-macosx
via git bisect, 074d61c4845f22939b29a8024129f892e609d0f0 is the commit which introduces this problem.
I added the following spec to compiler/codegen/if_spec.cr to test for the condition.
it "doesn't detect type in else condition (bug)" do
codegen(%(
v = nil : String
if v.nil?
else
sizeof(typeof(v))
end
))
end
I'm still not familiar with why that code was added, but I'm still poking around.
I forked and branched to show the test:
https://github.com/ddrscott/crystal/tree/ISSUE_5717
So the problem is that sizeof should raise an error when called for an empty type, but sometimes this can happen on legitimate code (in a branch that is never executed). How can it be solved?
Is it possible to:
nil value. So in this case I'd expect 8 to be returned.
Most helpful comment
Huh, i tried and looks like problem isn't so scary.
basically, test case is
in real code it happens because v is an input argument of a method, so usually it is a union or not nil, but sometimes it is called directly with nil.