On type annotations

The second one performs a conversion before assigning to x and is equivalent > to

x = convert(T, foo())::T

Perhaps you meant this?

x::T = convert(T, foo())

Afaik, the return value of convert is already of type T and it does not need to be asserted. The difference is important for the discussion as x::T guarantees that x will not change type until it goes end of scope.

Indeed, convert may be called. It is only called though when there is something to convert. A function annotated with ::S returning a local variable of type S will not induce a call to convert. So the performance hit is absent in this case. We expect that developers will not introduce a lot of convert methods for other cases.

julia> import Base.convert

julia> struct S
                  mem::Int64
              end

julia> function convert(::Type{S}, x::Any)::S
                  println("convert(...): Started.")
                  return S(x)
              end
convert (generic function with 196 methods)

julia> function return_right_type(s::S)::S
                  return S(s.mem * s.mem)
              end
return_right_type (generic function with 1 method)

julia> u::S = return_right_type(S(42))
S(1764)

julia> v::S = 5
convert(...): Started.
5

julia> 
1 Like