Docs say that type annotations on variables and return types of functions facilitate type inference and performance. But does the opposite hold? If I have a function:
function foo(x)::Number
if isa(x, Number)
return x
else
return 0
end
end
Will the convert(Number, ...)
method be called on the return value of foo
, or it will be a no-op, for it is clear that both x
and 0
are Number
s?
In general, if I have a variable with type annotation, is convert
called at every assignment to the variable or it optimized away whenever type inference is sure about the type of RHS?
1 Like
Julia has excellent tools to answer those questions
E.g. use @code_warntype
and @code_lowered
to figure out what happens (you can use ?@code_lowered
in the REPL to get the doc string for those macros):
julia> function foo(x)::Number
if isa(x, Number)
return x
else
return 0
end
end
foo (generic function with 1 method)
julia> @code_lowered foo(1)
CodeInfo(:(begin
nothing
SSAValue(0) = Main.Number
unless x isa Main.Number goto 6 # line 3:
return (Core.typeassert)((Base.convert)(SSAValue(0), x), SSAValue(0))
6: # line 5:
return (Core.typeassert)((Base.convert)(SSAValue(0), 0), SSAValue(0))
end))
julia> @code_warntype foo(1)
Variables:
#self# <optimized out>
x::Int64
Body:
begin # line 3:
return x::Int64 # line 5:
end::Int64
julia> @code_warntype foo(1.0)
Variables:
#self# <optimized out>
x::Float64
Body:
begin # line 3:
return x::Float64 # line 5:
end::Float64
julia> @code_warntype foo("1")
Variables:
#self# <optimized out>
x <optimized out>
Body:
begin
goto 3 # line 3:
3: # line 5:
return 0
end::Int64
So Julia seems to turn each return
into convert(Number, x)::Number
. The type assert and convert get inlined and removed.
4 Likes
@sdanisch Indeed, thanks a lot!