class Object
def map?(&block)
if nil?
nil
else
yield self
end
end
end
puts "foo".map?(&.upcase).inspect
puts nil.map?(&.upcase).inspect
a = if rand > 0.5
"foo"
else
nil
end
puts a.map?(&.upcase).inspect
Error message on crystal build:
BUG: trying to assign Nil <- String (Exception)
from Crystal::CodeGenVisitor#assign<LLVM::Value, Crystal::Type+, Crystal::Type+, LLVM::Value>:(Bool | LLVM::Value | Nil)
from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
from Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)
from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
from Crystal::ASTNode+@Crystal::ASTNode#accept<Crystal::CodeGenVisitor>:Nil
from Crystal::CodeGenVisitor#prepare_call_args_non_external<Crystal::Call, Crystal::Def+, Crystal::Type+>:Tuple(Array(LLVM::Value), Bool)
from Crystal::CodeGenVisitor#visit<Crystal::Call>:Bool
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#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
Crystal version is
Crystal 0.26.1 (2018-08-27) │
│
LLVM: 6.0.1 │
Default target: x86_64-apple-macosx
macOS is version 10.13.4
I'll leave it up as this should probably not cause a compiler bug, but for anyone still relatively new to Crystal looking at this:
The above is trying to reproduce behavior already present with Object#try. My guess is there are issues because Nil is a struct, not a class.
I guess the trouble is that self is not restricted to non-nil. However, it doesn't work when storing it in a local variable, either.
This however is a working solution, similar to how .try is implemented:
class Object
def map?(&block)
yield self
end
end
struct Nil
def map?(&block)
nil
end
end
Nevertheless, the initial code should either work or raise a proper error, not a compiler bug.
Fixed? The original example now gives
"FOO"
nil
nil
Crystal 0.31.1 on MacOS
$ crystal --version
Crystal 0.31.1 (2019-10-02)
LLVM: 8.0.1
Default target: x86_64-apple-macosx
Indeed, nil? is now parsed like self.nil? and so usual type flow restrictions now apply.
Most helpful comment
Fixed? The original example now gives
Crystal 0.31.1 on MacOS