Crystal: Merging a proc returning void with a proc returning non-void should be a proc returning void

Created on 28 May 2016  路  6Comments  路  Source: crystal-lang/crystal

This should work:

class Foo
  @action : ->
  def initialize
    @action = -> { }
  end
end

Foo.new

Extracted from: https://github.com/crystal-lang/crystal/issues/2666#issuecomment-222317868

feature compiler

Most helpful comment

It vanishes if one explicitly puts nil at the end of the proc. Maybe this should work:

class Foo
  @action : -> # Now this would be the same as `-> Nil`
  def initialize
    @action = -> { 1 } # this is -> Int32, but we said we don't care about the return value,
                       # so maybe it should work
  end
end

Foo.new

All 6 comments

Since Void accepts every value, Void? or generally Void|Foo should either degrade into just Void or be disallowed, WDYT?

On second though, I'm not sure about this. For example:

proc1 = ->{ 1 }
proc2 = Proc(Void).new { ... }

proc = rand < 0.5 > proc1 : proc2
value = proc.call
# value should be Void | Int32, not Void

I wouldn't like to mess with types there, and loose some type information. So to solve the snippet in the original comment one can do:

class Foo
  @action : ->
  def initialize
    @action = Proc(Void).new { ... }
  end
end

Foo.new

I'll mark it as a draft RFC because this needs more thought.

Actually, that should work, but right now the compiler doesn't distinguish between "assigning something to a variable" and "merging types": when it assigns something to a variable it first merges its type with the type of the right-hand side, and then sets that final type as the instance variable type. I'll try to improve this first.

If we do follow https://github.com/crystal-lang/crystal/issues/2666#issuecomment-222318426 this issue basically vanishes, no?

It vanishes if one explicitly puts nil at the end of the proc. Maybe this should work:

class Foo
  @action : -> # Now this would be the same as `-> Nil`
  def initialize
    @action = -> { 1 } # this is -> Int32, but we said we don't care about the return value,
                       # so maybe it should work
  end
end

Foo.new

I'd say plan forward would to get rid of Void and then tackle this issue for Nil

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jhass picture jhass  路  3Comments

costajob picture costajob  路  3Comments

TechMagister picture TechMagister  路  3Comments

lbguilherme picture lbguilherme  路  3Comments

ArthurZ picture ArthurZ  路  3Comments