class A
@@a : String -> Void
@@a = ->(y : String){
1
}
end
compiler complains Proc type doesn't match.
Because your block returns 1, thus is a Proc(String, Int32) not a Proc(String, Nil).
@ysbaddaden but the following code can be compiled.
def foo (&block : Int32 -> Void)
yield 1
end
foo do
1
end
Right now the compiler, in many places, to determine the type of something, just takes the type on the left-hand side, the type on the right-hand side, combines them, and tries to assign the result to the left-hand side. Here a union is created and it doesn't match the original type.
However, since we introduced explicit types in instance variables this rule can be changed or relaxed. In those cases we should try to see if the right-hand side can be implicitly converted to the left-hand side.
In the case of a block, it's simpler: if the block specification returns Void (or Nil, please use Nil instead of Void), then the block's type is inferred to be Nil.
I'll mark this as an enhancement.
A simple workaround is of course:
class A
@@a : String -> Nil
@@a = ->(y : String){
1
nil
}
end
Could this be bumped? Me and a few others have run into this. It is a bit strange since return types on regular methods set to Nil will be coerced to nil, but not the same for Procs. This has led to a fair bit of confusion so I wonder if it could be prioritized?
Also just for clarity to anyone reading this that isn't familiar:
def my_method : Nil
"a string"
end
Will still compile. This is basically Void return type in other languages. But doing it for a Proc currently requires an explicit nil return
PR's are welcome :+1:
I can try to see if I can merge procs of same argument types and Nil and T return types into Nil return type. Maybe that'll work and it makes sense.
Most helpful comment
I can try to see if I can merge procs of same argument types and
NilandTreturn types intoNilreturn type. Maybe that'll work and it makes sense.