Generic way to dispatch on type of Union type

I tried to write methods for a function (taking types as arguments) that should dispatch only if one argument supertypes the other, e.g.,

a_supertypes_b( a::Type, b::Type ) = "no"
a_supertypes_b( ::Type{SUP}, ::Type{SUB} ) where {SUP, SUB<:SUP} = "yes"

Of course, my use case was not checking the type relation, but the method signatures looked similar.
Now, I also wanted a custom method for the case that the supertype SUP was a Union type.
Is there a generic way to dispatch on “types of Union types”?
First thought:

a_supertypes_b( ::Type{SUP}, ::Type{SUB} ) where {SUP<:Union, SUB<:SUP} = "yes_for_union"

This does not get called:

T32 = Union{Int32, Float32}
a_supertypes_b( T32, Int32 ) == "yes" # not "yes_for_union"

I think, this is because T32 isa Type{<:Union} is false.
In fact, for any Union type, typeof returns simply Union.
This is also why

a_supertypes_b( :: SUP, :: Type{SUB} ) where {SUP<:Union, SUB<:SUP} = "yes_for_union"

won’t get called for (T32, Int32): Then SUP == Union and it does not hold that Int32 <: Union.

In all of the above examples, the method for union types does not get called, because typeof(T32) != Type{T32} which would discourage from using the dispatch mechanism for types of union types.
However, I know that I can use handwritten method signatures, e.g.,

T64 = Union{Int64, Float64}
f( :: Type{Union{Int32, Float32}} ) = 32
f( :: Type{T64} ) = 64
# now this is true:
f(T32) == 32 && f(T64) == 64


a_supertypes_b( :: Type{SUP}, SUB ) where {SUP<:T32, SUB<:SUP} = "yes_T32"

would get called: a_supertypes_b( T32, Int32 ) == "yes_T32".
So in the above example, for the union type T32, Julia dispatches on Type{T32} (and not on typeof(T32) == Union).

Can I do this generically, if the exact union types are not known beforehand?
I guess, one difficulty prohibiting a generalization of the last method definition for arbitrary union types lies in the fact, that there is no defining supertype of union types. That is, there is no SUP_UNION such that T <: SUP_UNION for any union type T, which would allow for

a_supertypes_b( :: Type{SUP}, SUB ) where {SUP<:SUP_UNION, SUB<:SUP} = "yes_for_union"

Or does such a supertype exist?
Am I overlooking something?
Thanks in advance!

No, and to quote Jeff “if you do that, please stop”. There’s a juliacon talk from a few years ago where jeff mentions this exact thing, I’ll link it once I find it again. There’s also an issue for this sort of thing, the keywords are “dispatch on type representation”.

1 Like

This is the talk:

The part I’m talking about is at 15:15, but the whole section starting at 13:00 is probably best for context.

1 Like

Ok, thank you very much! I think I am beginning to see the problems.
Here is a related issue on GitHub: redesign typeof(::Type) · Issue #29368 · JuliaLang/julia · GitHub

1 Like