Description
I found that there is a pitfall with dispatching on custom parameterized types due to Type{Union{}} <: Type{<:MyType}
(JuliaArrays/StaticArrays.jl#685). Borrowing @c42f's example, the problem is that:
julia> foo(::Type{T}) where {T} = "generic" julia> foo(::Type{<:Int}) = "special" julia> foo(Union{}) "special"
For a concrete type like Int
, the solution is to write Type{Int}
. However, it is tricky for parameterized types. Possible workarounds are:
-
Use
foo(::Type{T}) where {P, MyType{P} <: T <: MyType}
: However, this interferes with the inliner Unpirate Union{}[] JuliaArrays/StaticArrays.jl#685 (comment) possibly due to unbound type parameters (see also Remove some spuriouswhere T
from SA constructors JuliaArrays/StaticArrays.jl#665, lower bound interferes with typevar value inference #30713). -
Separate dispatches as in
foo(::Type{MyType})
andfoo(::Type{MyType{P}}) where P
. Unpirate Union{}[] JuliaArrays/StaticArrays.jl#685 uses this solution. -
Write a helper function like
Type₁(U) = Type{T} where {P, U{P} <: T <: U}
and then definefoo(::Type₁(MyType))
.
However, none of the above solutions works well when there are many parameters. It may be useful to have a generalization of approach 3 (say) Type₊(U::UnionAll)
that works with an arbitrary number of parameters. Or maybe there is a better solution?