I tried to subtract a type T
from a union type with this function (a “poor man’s Core.Compiler.typesubtract
”):
typesubtract(::Type{Union{T,S}}, ::Type{T}) where {S, T} = S
typesubtract(::Type{S}, ::Type{T}) where {S, T} = S
typesubtract(::Type{T}, ::Type{T}) where {T} = Union{}
However, this function did not work for simple case like typesubtract(Union{Missing, Float64, Int}, Missing)
which returns Union{Missing, Float64, Int64}
while I expected Union{Float64, Int}
.
On the other hand, just flipping arguments as the function union_poptype
works (This is taken from @galenlynch’s PR #30549):
union_poptype(::Type{T}, ::Type{Union{T,S}}) where {T, S} = S
union_poptype(::Type{T}, ::Type{S}) where {T, S} = S
union_poptype(::Type{T}, ::Type{T}) where {T} = Union{}
Why union_poptype
works and my typesubtract
doesn’t? Does Julia’s dispatch system depend on order of arguments? I thought the type system prefers to throw ambiguity error rather than using argument order to break ties.
I checked those functions using
using Test
@testset "union_poptype" begin
@test union_poptype(Missing, Union{Missing, Float64, Int}) == Union{Float64, Int}
@test union_poptype(Missing, Union{Missing, Float64}) == Float64
@test union_poptype(Missing, Union{Float64, Int}) == Union{Float64, Int}
@test union_poptype(Missing, Float64) == Float64
end
@testset "typesubtract" begin
@test typesubtract(Union{Missing, Float64, Int}, Missing) == Union{Float64, Int}
@test typesubtract(Union{Missing, Float64}, Missing) == Float64
@test typesubtract(Union{Float64, Int}, Missing) == Union{Float64, Int}
@test typesubtract(Float64, Missing) == Float64
end
which yields
Test Summary: | Pass Total
union_poptype | 4 4
typesubtract: Test Failed at ...
Expression: typesubtract(Union{Missing, Float64, Int}, Missing) == Union{Float64, Int}
Evaluated: Union{Missing, Float64, Int64} == Union{Float64, Int64}
...
typesubtract: Test Failed at ...
Expression: typesubtract(Union{Missing, Float64}, Missing) == Float64
Evaluated: Union{Missing, Float64} == Float64
Stacktrace:
...
Test Summary: | Pass Fail Total
typesubtract | 2 2 4