Typeof with begin/rescue/else

Hello,
Could you help me understand the following behaviour ?

# with 0.33.0

puts typeof(
  begin
    1.3
  rescue
    1
  end
)
#=> (Float64 | Int32) 

begin
  puts 1.3
rescue
  puts 1
end
#=> 1.3

How can I get Int32 ? It looks like it entered the rescue clause.

If I add an else clause, it seems to go through both clauses :

puts typeof(
  begin
    1.3
  rescue
    1
  else
    "1"
  end
)
#=> (Int32 | String)

Thank you

Jo

The reasoning the first example is a union of Float64 | Int32 is because those are the types that could possibly be returned. I.e. the compiler doesn’t actually know if there will be an exception or not since that happens at runtime. If there is no exception, then the value in the begin portion of it is returned, which is a Float64. If there is an exception, then the value in the rescue part of it is returned, which is an Int32. Thus, the compiler is telling you the resulting value of this statement can be Float64 OR Int32.

The second example is similar. However, in this case Float64 is removed from the union since the statement will never return the value within the begin portion. The reason for this is because of what the else does:

An else clause is executed only if no exceptions were rescued:

If there is no exception the value in the else portion would be used, which would be a String, otherwise the value in the rescue portion would be used, which is an Int32. Thus resulting in your union of String | Int32.

4 Likes

Thank you for your answer :)