Skip to content

Dispatch pitfall due to Type{Union{}} <: Type{<:MyType}. #33780

Closed
@tkf

Description

@tkf

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:

  1. 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 spurious where T from SA constructors JuliaArrays/StaticArrays.jl#665, lower bound interferes with typevar value inference #30713).

  2. Separate dispatches as in foo(::Type{MyType}) and foo(::Type{MyType{P}}) where P. Unpirate Union{}[] JuliaArrays/StaticArrays.jl#685 uses this solution.

  3. Write a helper function like Type₁(U) = Type{T} where {P, U{P} <: T <: U} and then define foo(::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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    types and dispatchTypes, subtyping and method dispatch

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions