Is there a difference between function my_func(x::SomeAbstractType) and my_func(x::T) where T <: SomeAbstractType

It doesn’t look like it based on output from @code_lowered and @code_native, but I also didn’t read that these are explicitly equivalent. Clearly they are not equivalent in the case of some containing type (e.g. Point{T} where T<:Real and Point{Real} are not the same) but are they equivalent otherwise? If so, is one preferred? If not, what is the difference?

abstract type SomeAbstractType end

struct ConcreteType <: SomeAbstractType
    field1::Float64
end

function my_func_v1(x::SomeAbstractType)
    x.field1 + 1.0
end

function my_func_v2(x::T) where T <: SomeAbstractType
    x.field1 + 1.0
end

julia> @code_lowered my_func_v1(ConcreteType(1.0))
CodeInfo(
xyz 1 ─ %1 = (Base.getproperty)(x, :field1)                                                     │
    │   %2 = %1 + 1.0                                                                           │
    └──      return %2 

julia> @code_lowered my_func_v2(ConcreteType(1.0))
CodeInfo(
xyz 1 ─ %1 = (Base.getproperty)(x, :field1)                                                     │
    │   %2 = %1 + 1.0                                                                           │
    └──      return %2                                                                          │
)

There is no functional difference, but as a matter of style, you should use the first version in function signatures, unless you have need of T inside the body. Even then you can use typeof.

1 Like