crystal
crystal copied to clipboard
BUG: `typeof` has no type
The following code triggers a compiler error:
input = 1
if input = input.is_a?(Int32)
typeof(input) # BUG: `typeof(input)` at eval:3:3 has no type
end
Interestingly, when typeof(input)
is used as a call argument, what was previously declared a compiler bug now becomes an unhandled compiler exception:
input = 1
if input = input.is_a?(Int32)
puts typeof(input) # Unhandled exception: can't execute `puts(typeof(input))` at eval:3:3: `typeof(input)` has no type
end
Might be related to #9702 and #11054
typeof
is not that relevant it seems, the following triggers the same error:
input = 1
if input = input.is_a?(Int32)
puts input
end
This already triggers the error.
As I understand it, the typechecker tries to be smart by considering impossible cases:
x = nil
if x.is_a?(Int32)
x + "" # OK, this will never be executed
end
The compiler infers that x
should be Nil
and Int32
, in the body of the if, but that's impossible. In the example I posted before the compiler infers the same, but actually the execution will return a truthy value.
The compiler infers that x should be Nil and Int32, in the body of the if
No, I think just Int32
. Why also Nil
?
I don't know really, I'm just guessing what the typechecker is doing here, and my interpretation is compatible with its behavior.
Type filters are applied according to variable names only, so they do not account for the possibility that the variables could be different yet. Another example:
x = 1
if x.is_a?(Int32) && (x = 'a'; "")
p x
end
This applies the Int32
type filter on the second x
, which is now a Char
and does not produce a filter. Since Int32 & Char == NoReturn
no type inference is done inside the then-clause. The correct behavior is to discard all type filters (positive or negative) on a variable whenever it is assigned, but possibly allow the truthy filter to take effect afterwards.