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 Numbers?
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?
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.
@sdanisch Indeed, thanks a lot!