Crystal: Compiler error when using a method defined on Object for an variable of type T | Nil

Created on 21 Sep 2018  Â·  4Comments  Â·  Source: crystal-lang/crystal

Reproducing Code Sample

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

bug compiler

Most helpful comment

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

All 4 comments

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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

oprypin picture oprypin  Â·  3Comments

asterite picture asterite  Â·  3Comments

grosser picture grosser  Â·  3Comments

Papierkorb picture Papierkorb  Â·  3Comments

lbguilherme picture lbguilherme  Â·  3Comments