Trait inheritance

Is it possible to dispatch on a trait inheritance hierarchy without invoking dynamic dispatch?

if dispatch can be determined at compile time it will be for example:

struct SomeType
       x::Int 
end

struct SomeTrait end

hasSomeTrait(::SomeType) = SomeTrait()
hasSomeTrait(::Any) = nothing

f(x) = f(x,hasSomeTrait(x))
f(x,::SomeTrait) = 3
f(x,::Any) = 4

If we look at the code produced we can see that the compiler used static dispatch. It can do this because of constant propagation.

julia> @code_llvm f(SomeType(2))

;  @ REPL[5]:1 within `f'
define i64 @julia_f_12189({ i64 } addrspace(11)* nocapture nonnull readonly dereferenceable(8)) {
top:
  ret i64 3
}
2 Likes

Thanks. Yes, but that’s only one level.

For example, what if I’d like to dispatch on an abstract trait type from which SomeTrait is a subtype?

so something more like the following?

abstract type AbstractSomeType end
struct SomeType <: AbstractSomeType
       x::Int 
end

abstract type AbstractSomeTrait end
struct SomeTrait <: AbstractSomeTrait end

hasSomeTrait(::AbstractSomeType) = SomeTrait()
hasSomeTrait(::Any) = nothing

f(x) = f(x,hasSomeTrait(x))
f(x,::AbstractSomeTrait) = 3
f(x,::Any) = 4

In this case we can see that it still uses static dispatch

julia> @code_llvm f(SomeType(2))

;  @ REPL[7]:1 within `f'
define i64 @julia_f_12188({ i64 } addrspace(11)* nocapture nonnull readonly dereferenceable(8)) {
top:
  ret i64 3
}
2 Likes

That looks great. Thanks!